How do you rotate a two dimensional array?

后端 未结 30 3568
耶瑟儿~
耶瑟儿~ 2020-11-22 02:43

Inspired by Raymond Chen\'s post, say you have a 4x4 two dimensional array, write a function that rotates it 90 degrees. Raymond links to a solution in pseudo code, but I\'d

30条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 03:41

    As I said in my previous post, here's some code in C# that implements an O(1) matrix rotation for any size matrix. For brevity and readability there's no error checking or range checking. The code:

    static void Main (string [] args)
    {
      int [,]
        //  create an arbitrary matrix
        m = {{0, 1}, {2, 3}, {4, 5}};
    
      Matrix
        //  create wrappers for the data
        m1 = new Matrix (m),
        m2 = new Matrix (m),
        m3 = new Matrix (m);
    
      //  rotate the matricies in various ways - all are O(1)
      m1.RotateClockwise90 ();
      m2.Rotate180 ();
      m3.RotateAnitclockwise90 ();
    
      //  output the result of transforms
      System.Diagnostics.Trace.WriteLine (m1.ToString ());
      System.Diagnostics.Trace.WriteLine (m2.ToString ());
      System.Diagnostics.Trace.WriteLine (m3.ToString ());
    }
    
    class Matrix
    {
      enum Rotation
      {
        None,
        Clockwise90,
        Clockwise180,
        Clockwise270
      }
    
      public Matrix (int [,] matrix)
      {
        m_matrix = matrix;
        m_rotation = Rotation.None;
      }
    
      //  the transformation routines
      public void RotateClockwise90 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 1) & 3);
      }
    
      public void Rotate180 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 2) & 3);
      }
    
      public void RotateAnitclockwise90 ()
      {
        m_rotation = (Rotation) (((int) m_rotation + 3) & 3);
      }
    
      //  accessor property to make class look like a two dimensional array
      public int this [int row, int column]
      {
        get
        {
          int
            value = 0;
    
          switch (m_rotation)
          {
          case Rotation.None:
            value = m_matrix [row, column];
            break;
    
          case Rotation.Clockwise90:
            value = m_matrix [m_matrix.GetUpperBound (0) - column, row];
            break;
    
          case Rotation.Clockwise180:
            value = m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column];
            break;
    
          case Rotation.Clockwise270:
            value = m_matrix [column, m_matrix.GetUpperBound (1) - row];
            break;
          }
    
          return value;
        }
    
        set
        {
          switch (m_rotation)
          {
          case Rotation.None:
            m_matrix [row, column] = value;
            break;
    
          case Rotation.Clockwise90:
            m_matrix [m_matrix.GetUpperBound (0) - column, row] = value;
            break;
    
          case Rotation.Clockwise180:
            m_matrix [m_matrix.GetUpperBound (0) - row, m_matrix.GetUpperBound (1) - column] = value;
            break;
    
          case Rotation.Clockwise270:
            m_matrix [column, m_matrix.GetUpperBound (1) - row] = value;
            break;
          }
        }
      }
    
      //  creates a string with the matrix values
      public override string ToString ()
      {
        int
          num_rows = 0,
          num_columns = 0;
    
        switch (m_rotation)
        {
        case Rotation.None:
        case Rotation.Clockwise180:
          num_rows = m_matrix.GetUpperBound (0);
          num_columns = m_matrix.GetUpperBound (1);
          break;
    
        case Rotation.Clockwise90:
        case Rotation.Clockwise270:
          num_rows = m_matrix.GetUpperBound (1);
          num_columns = m_matrix.GetUpperBound (0);
          break;
        }
    
        StringBuilder
          output = new StringBuilder ();
    
        output.Append ("{");
    
        for (int row = 0 ; row <= num_rows ; ++row)
        {
          if (row != 0)
          {
            output.Append (", ");
          }
    
          output.Append ("{");
    
          for (int column = 0 ; column <= num_columns ; ++column)
          {
            if (column != 0)
            {
              output.Append (", ");
            }
    
            output.Append (this [row, column].ToString ());
          }
    
          output.Append ("}");
        }
    
        output.Append ("}");
    
        return output.ToString ();
      }
    
      int [,]
        //  the original matrix
        m_matrix;
    
      Rotation
        //  the current view of the matrix
        m_rotation;
    }
    

    OK, I'll put my hand up, it doesn't actually do any modifications to the original array when rotating. But, in an OO system that doesn't matter as long as the object looks like it's been rotated to the clients of the class. At the moment, the Matrix class uses references to the original array data so changing any value of m1 will also change m2 and m3. A small change to the constructor to create a new array and copy the values to it will sort that out.

提交回复
热议问题