首页 > 代码库 > 矩阵旋转90度(keep it up)

矩阵旋转90度(keep it up)

一张图像表示成NxN的矩阵,图像中每个像素是4个字节,写一个函数把图像旋转90度。 你能原地进行操作吗?(即不开辟额外的存储空间)

这个题第一感觉就是一次交换矩阵的元素:

比如 3*3 矩阵

1 2 3
4 5 6
7 8 9
先处理第一行,一次逆时针旋转四个元素,下面是二次做的
3 2 9          3 6 9
4 5 6          2 5 8
1 8 7          1 4 7
第一次         第二次

如果是5*5的矩阵
1   2   3   4   5
6   7   8   9   10
11  12  13  14  15
16  17  18  19  20
21  22  23  24  25 
一下是处理第一行后的变化
5   2   3   4   25  
6   7   8   9   10
11  12  13  14  15
16  17  18  19  20
1   22  23  24  21
第1次

5   10  3   4   25  
6   7   8   9   24
11  12  13  14  15
2   17  18  19  20
1   22  23  16  21
第2次

5   10  15  4   25  
6   7   8   9   24
3   12  13  14  23
2   17  18  19  20
1   22  11  16  21
第3次

5   10  15  20  25  
4   7   8   9   24
3   12  13  14  23
2   17  18  19  22
1   6   11  16  21
第4次


第一行处理之后
剩下没处理的是一个3*3的矩阵
7   8   9
12  12  13
17  18  19
在按照3*3处理最后就得到结果
5  10  15  20  25
4  9   14  19  24
3  8   13  18  23
2  7   12  17  22
1  6   11  16  21
但在写代码时,这种想法编码比较麻烦,要处理数组下标计算,很麻烦。

下面介绍另一种方法
我们看 4*4的矩阵
1  2  3  4
5  6  7  8
9  10 11 12
13 14 15 16
我们线交换主对角线两边的元素:
1  5  9  13
2  6  10 14
3  7  11 15
4  8  12 16
然后在交换第i行和第n-i-1行的元素就得到结果
4  8  12  16
3  7  11  15
2  6  10  14
1  5  9   13

下面是代码:

#define N 4

void swap(int& vLeft, int& vRight)
{
	int Temp = vLeft;
	vLeft  = vRight;
	vRight = Temp;
}

//逆时针旋转
void rotate_matrix(int vMat[N][N])
{
	//先交换主对角线两边的元素, 如果是顺时针旋转,交换副对角线两边的元素
	for (int i=0; i<N; ++i)
	{
		for (int k=i+1; k<N; ++k)
		{
			swap(vMat[i][k], vMat[k][i]);
		}
	}

	//在交换i行与N-i-1行的元素
	for (int i=0; i<N/2; ++i)
	{
		for (int k=0; k<N; ++k)
		{
			swap(vMat[i][k], vMat[N-i-1][k]);
		}
	}
}

void print_matrix(int vMat[N][N])
{
	for (int i=0; i<N; ++i)
	{
		for (int k=0; k<N; ++k)
		{
			printf("%3d ", vMat[i][k]);
		}
		printf("\n");
	}
}

int main()
{
	int a[N][N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

	print_matrix(a); printf("\n");
	rotate_matrix(a);
	print_matrix(a);

	system("pause");
	return 0;
}