二维数组的旋转与翻转(C++)(下(这是仔细讲解))

一、二维数组旋转与翻转的基本概念(C++)

(一)二维数组旋转的概念

在C++中,二维数组的旋转是指将数组中的元素按照一定的规则进行重新排列,从而实现整个数组或者部分数组在平面上的顺时针或者逆时针旋转。这就好比将一个矩形(以二维数组表示)在平面上绕着某个点进行转动。 例如,对于一个3x3的二维数组(可以看作是一个3行3列的矩阵):

1 2 3
4 5 6
7 8 9

如果进行顺时针90度旋转后,它将变成:

7 4 1
8 5 2
9 6 3

这里的旋转涉及到元素位置的对应关系的转换。从整体的概念理解,它改变了数组元素的行列关系。在更深入的理解上,这种旋转操作实际上是对数组元素坐标的一种变换操作。设原始数组为A,旋转后的数组为B,以顺时针旋转为例,元素A[i][j]在旋转后将变为B[j][n - 1 - i](其中n为数组的阶数,这里假设数组是n x n的正方形数组)。这一转换关系是通过分析每个元素在旋转前后的位置得出的。例如,在3x3数组中,A[0][0](值为1)在顺时针旋转后将位于新数组的B[0][2]位置。这一关系的确定对于编写旋转算法至关重要。同时,旋转还可以分为整体旋转和局部旋转。整体旋转是对整个二维数组进行操作,而局部旋转则是针对数组中的某一部分区域进行旋转操作,例如以某个子矩阵为中心进行旋转1

(二)二维数组翻转的概念

二维数组的翻转是指将数组沿着某条轴线进行对称变换。这与旋转有所不同,翻转更多的是一种镜像操作。在C++中,常见的翻转方式有水平翻转和垂直翻转。

  1. 水平翻转

    • 对于一个二维数组进行水平翻转,就是将每一行的元素以该行的中心为对称轴进行交换。例如对于以下的3x3二维数组:

    1 2 3
    4 5 6
    7 8 9
    水平翻转后变为:
    3 2 1
    6 5 4
    9 8 7

    从元素的角度来看,对于第i行,A[i][j]将变为A[i][n - 1 - j](n为该行的元素个数)。

  2. 垂直翻转

    • 垂直翻转则是将每一列的元素以该列的中心为对称轴进行交换。对于上述的3x3二维数组,垂直翻转后将变为:

    7 8 9
    4 5 6
    1 2 3

    此时,对于第j列,A[i][j]将变为A[n - 1 - i][j](n为数组的行数)。 这种翻转操作在图像处理、矩阵变换等领域有着广泛的应用,例如在图像的上下颠倒或者左右反转操作中,就可以通过对表示图像像素的二维数组进行垂直或者水平翻转来实现11

二、二维数组旋转与翻转的实现方法(C++)

(一)二维数组旋转的实现方法

  1. 整体旋转

    • 顺时针旋转

      • 首先要确定旋转的对应关系。以n x n的二维数组为例,对于原始数组A和旋转后的数组B,元素的对应关系为B[i][j]=A[n - 1 - j][i]。在C++中实现时,可以使用嵌套的for循环来遍历数组。外层循环控制行,内层循环控制列。例如:

      #include <iostream>
      
      const int N = 3; 
      
      void rotateClockwise(int A[][N], int B[][N]) {
          for (int i = 0; i < N; i++) {
              for (int j = 0; j < N; j++) {
                  B[i][j] = A[N - 1 - j][i]; 
              }
          }
      }
      
      int main() {
          int A[N][N] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 
          int B[N][N]; 
          rotateClockwise(A, B); 
          for (int i = 0; i < N; i++) {
              for (int j = 0; j < N; j++) {
                  std::cout << B[i][j] << " "; 
              }
              std::cout << std::endl; 
          }
          return 0; 
      }

      • 在这个代码中,rotateClockwise函数实现了将二维数组A顺时针旋转并存储到数组B中的功能。通过双层for循环,按照前面提到的对应关系对每个元素进行赋值。

    • 逆时针旋转

      • 逆时针旋转的对应关系为B[i][j]=A[j][n - 1 - i]。同样使用嵌套的for循环来实现。例如:

      #include <iostream>
      
      const int N = 3; 
      
      void rotateCounterClockwise(int A[][N], int B[][N]) {
          for (int i = 0; i < N; i++) {
              for (int j = 0; j < N; j++) {
                  B[i][j] = A[j][N - 1 - i]; 
              }
          }
      }
      
      int main() {
          int A[N][N] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 
          int B[N][N]; 
          rotateCounterClockwise(A, B); 
          for (int i = 0; i < N; i++) {
              for (int j = 0; j < N; j++) {
                  std::cout << B[i][j] << " "; 
              }
              std::cout << std::endl; 
          }
          return 0; 
      }

  2. 局部旋转

    • 对于局部旋转,需要先确定要旋转的区域。假设要以(x,y)为中心,对一个2r + 1阶的子矩阵进行旋转。首先要将坐标转换为以子矩阵左上角为基准的相对坐标。然后按照整体旋转的思路确定对应关系。例如,对于顺时针局部旋转,在相对坐标下的对应关系为B[i][j]=A[2r - j][i](这里假设子矩阵的边长为2r+1)。在C++实现中,除了双层for循环遍历子矩阵区域外,还需要注意边界条件的处理,确保不会访问到数组越界的元素。

(二)二维数组翻转的实现方法

  1. 水平翻转

    • 要实现二维数组的水平翻转,可以使用嵌套的for循环。外层循环遍历每一行,内层循环对每一行的元素进行交换。例如,对于一个m x n的二维数组A,以下是实现水平翻转的代码片段:

    #include <iostream>
    
    const int M = 3; 
    const int N = 3; 
    
    void horizontalFlip(int A[][N]) {
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N / 2; j++) {
                int temp = A[i][j]; 
                A[i][j] = A[i][N - 1 - j]; 
                A[i][N - 1 - j] = temp; 
            }
        }
    }
    
    int main() {
        int A[M][N] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 
        horizontalFlip(A); 
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                std::cout << A[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
        return 0; 
    }

    • 在这个代码中,horizontalFlip函数通过交换每一行的对称元素实现了水平翻转。内层循环只需要遍历到列数的一半,因为每次交换是成对进行的。

  2. 垂直翻转

    • 垂直翻转的实现类似,只是交换的是列元素。外层循环遍历列,内层循环对每列的元素进行交换。例如:

    #include <iostream>
    
    const int M = 3; 
    const int N = 3; 
    
    void verticalFlip(int A[][N]) {
        for (int j = 0; j < N; j++) {
            for (int i = 0; i < M / 2; i++) {
                int temp = A[i][j]; 
                A[i][j] = A[M - 1 - i][j]; 
                A[M - 1 - i][j] = temp; 
            }
        }
    }
    
    int main() {
        int A[M][N] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 
        verticalFlip(A); 
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                std::cout << A[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
        return 0; 
    }

    • 这里的verticalFlip函数通过交换每列的对称元素实现了垂直翻转。内层循环只需要遍历到行数的一半8

三、二维数组旋转与翻转的示例代码(C++)

(一)二维数组旋转示例代码

  1. 整体顺时针旋转示例

    • 以下是一个更完整的整体顺时针旋转二维数组的示例代码,包括了输入数组的初始化和结果的输出:

    #include <iostream>
    
    const int MAX_SIZE = 100; 
    
    // 顺时针旋转函数
    void rotateClockwise(int arr[][MAX_SIZE], int n) {
        int rotated[MAX_SIZE][MAX_SIZE]; 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rotated[i][j] = arr[n - 1 - j][i]; 
            }
        }
        // 输出旋转后的数组
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                std::cout << rotated[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
    }
    
    int main() {
        int n; 
        std::cout << "请输入二维数组的阶数: "; 
        std::cin >> n; 
        int arr[MAX_SIZE][MAX_SIZE]; 
        std::cout << "请输入二维数组的元素: "; 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                std::cin >> arr[i][j]; 
            }
        }
        rotateClockwise(arr, n); 
        return 0; 
    }

    • 在这个示例中,首先通过用户输入获取二维数组的阶数和元素,然后调用rotateClockwise函数进行顺时针旋转,并输出旋转后的数组。

  2. 整体逆时针旋转示例

    • 下面是整体逆时针旋转的示例代码:

    #include <iostream>
    
    const int MAX_SIZE = 100; 
    
    // 逆时针旋转函数
    void rotateCounterClockwise(int arr[][MAX_SIZE], int n) {
        int rotated[MAX_SIZE][MAX_SIZE]; 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                rotated[i][j] = arr[j][n - 1 - i]; 
            }
        }
        // 输出旋转后的数组
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                std::cout << rotated[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
    }
    
    int main() {
        int n; 
        std::cout << "请输入二维数组的阶数: "; 
        std::cin >> n; 
        int arr[MAX_SIZE][MAX_SIZE]; 
        std::cout << "请输入二维数组的元素: "; 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                std::cin >> arr[i][j]; 
            }
        }
        rotateCounterClockwise(arr, n); 
        return 0; 
    }

    • 这个代码与顺时针旋转的代码结构类似,只是在rotateCounterClockwise函数中,元素的赋值按照逆时针旋转的对应关系进行。

  3. 局部顺时针旋转示例

    • 假设要对以(x,y)为中心的3x3子矩阵进行顺时针旋转(这里假设整个二维数组足够大),以下是示例代码:

    #include <iostream>
    
    const int MAX_SIZE = 100; 
    
    // 局部顺时针旋转函数
    void localRotateClockwise(int arr[][MAX_SIZE], int x, int y) {
        int rotated[3][3]; 
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                rotated[i][j] = arr[x + 2 - j][y + i]; 
            }
        }
        // 将旋转后的子矩阵放回原数组
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                arr[x + i][y + j] = rotated[i][j]; 
            }
        }
    }
    
    int main() {
        int arr[MAX_SIZE][MAX_SIZE]; 
        // 这里简单初始化一个示例数组
        arr[0][0]=1; arr[0][1]=2; arr[0][2]=3; arr[0][3]=4; 
        arr[1][0]=5; arr[1][1]=6; arr[1][2]=7; arr[1][3]=8; 
        arr[2][0]=9; arr[2][1]=10; arr[2][2]=11; arr[2][3]=12; 
        arr[3][0]=13; arr[3][1]=14; arr[3][2]=15; arr[3][3]=16; 
        int x = 1; 
        int y = 1; 
        localRotateClockwise(arr, x, y); 
        // 输出旋转后的数组
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                std::cout << arr[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
        return 0; 
    }

    • 在这个代码中,localRotateClockwise函数首先对指定的3x3子矩阵进行顺时针旋转,将结果存储在临时数组rotated中,然后再将旋转后的子矩阵放回原数组中。

(二)二维数组翻转示例代码

  1. 水平翻转示例

    • 以下是一个完整的水平翻转二维数组的示例代码:

    #include <iostream>
    
    const int MAX_ROWS = 100; 
    const int MAX_COLS = 100; 
    
    // 水平翻转函数
    void horizontalFlip(int arr[][MAX_COLS], int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols / 2; j++) {
                int temp = arr[i][j]; 
                arr[i][j] = arr[i][cols - 1 - j]; 
                arr[i][cols - 1 - j] = temp; 
            }
        }
        // 输出翻转后的数组
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                std::cout << arr[i][j] << " "; 
            }
            std::cout << std::endl; 
        }
    }
    
    int main() {
        int rows, cols; 
        std::cout << "请输入二维数组的行数和列数: "; 
        std::cin >> rows >> cols; 
        int arr[MAX_ROWS][MAX_COLS]; 
        std::cout << "请输入二维数组的元素: "; 
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                std::cin >> arr[i][j]; 
            }
        }
        horizontalFlip(arr, rows, cols); 

    制作不易,点个赞吧┭┮﹏┭┮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值