解释“用最小空间度将一个M*N的矩阵旋转90度(顺逆时针均可) ”

来源:互联网 发布:qq飞车抽奖辅助软件 编辑:程序博客网 时间:2024/06/05 10:02
 引用别人的这个算法,对其进行勘误。

//功能:网上看到道题:用用最小空间度将一个M*N的矩阵旋转90度(顺逆时针均可) 
//       个人用五个额处空间(两个循环控制三个暂存)实现。 
//           大家一起研究,再优化,如果算法有错欢迎指正 
//           如果有更好的方法别忘了回贴 
//作者:陈昂(http974@163.com) 
//算法说明: 
//设有一个(M×N)3*4维矩阵A,旋转后成4*3 
//         1     2     3     4                       9     5     1 
//         5     6     7     8             =>       10   6     2 
//         9     10   11   12                     11   7     3 
//                                                   12   8     4 
//可以发现旋转后矩阵与原矩阵的关系: 
//           旋转后               原矩阵 
//           A[0,0]       =     A[2,0]     =   9 
//           A[0,1]       =     A[1,0]     =   5 
//           A[0,2]       =     A[0,0]     =   1 
//           A[1,0]       =     A[2,1]     =   10 
//           A[1,1]       =     A[1,1]     =   6 
//           A[1,2]       =     A[0,1]     =   2 
//           A[2,0]       =     A[2,2]     =   11 
//           A[2,1]       =     A[1,2]     =   7 
//           A[2,2]       =     A[0,2]     =   3 
//           A[3,0]       =     A[2,3]     =   12 
//           A[3,1]       =     A[1,3]     =   8 
//           A[3,2]       =     A[0,3]     =   4 
//可以得出对应关系为:旋转后矩阵A[i,j]   =   原矩阵A[   M-   j   -1,   i   ] 
//所以我们可以用一个矩阵来保存转换前后的值 
//用两层循环(注意外层为N,内层为M), 
//依次交换A[i,j]   与   A[   M-   j   -1,   i   ], 
//(交换不用额外存储空间,直接相加交换,如交换a和b的值:a=   a+   b;   b=   a-   b;   a   =   a   -   b) 
//这样可以求出A[i,j]的值,原来A[i,j]的值则保存在A[   M-   j   -1,   i   ]中 
//每一个A[i,j]都唯一对应一个A[   M-   j   -1,   i   ],所以我们从0开始依次求A[i,j]的值 
//要注意的是如果A[   M-   j-   1   ,i]在数组中存放的位置在A[i,j]之后,我们才做交换 
//如果A[   M-   j-   1   ,i]在A[i,j]之前,则说明A[   M-   j-   1   ,i]已经交换过,其值存在对应的 
//次A中,依次查找,直到找到位于A这后的对应元素即为该交换的值,下面用流程说明 
// 
//   ~A[x,y]表示A[i,j]对应在原矩阵中的元素. 
//   处理元素A[0,0](在数组中的位置为0),   其对应原矩阵的~A[2,0](对应位置为8),交换   
//   处理元素A[0,1](位置为1),~A[1,0](位置为4),交换 
//   处理元素A[0,2](位置为2),~A[0,0](位置为0),不交换, 
//   查找到位置为0的元素对应的~~A[2,0](位置为8),在其之后,即A[2,0]与A[0,0]交换过 
//   直接交换A[0,2]和A[2,0] 
//   依此类推。 
//   A[1,0](位置3)       ->     ~A[2,1](位置9) 
//   A[1,1](位置4)       ->     ~A[1,1](位置6) 
//   A[1,2](位置5)       ->     ~A[0,1](位置1)(交换过)     ->   ~~A[2,1]   =   A[1,0] //原文中这个地方是错误的,应该找到A[1,1],其主要原理就是

//将原来的M*N矩阵的坐标 转换成N*M的坐标,然后再找出对应的M*N矩阵也就是原矩阵的最后交换坐标。
//   ... 
//   A[3,2](位置11)     ->     ~A[0,3](位置2,对应新矩阵下标[1,0])(交换过)     
//                                   ->   ~~A[2,1](位置9)   ......   ~~~~A[2,3]   =   4 
//为便于理解,可画出下面三个矩阵。   
//           原矩阵                             (存储方式相同的矩阵)               旋转后           
//         1     2     3     4                             1     2     3                             9       5     1 
//         5     6     7     8             =>             4     5     6                   =>       10     6     2 
//         9     10   11   12                           7     8     9                             11     7     3 
//                                                         10   11   12                           12     8     4 

#include   <stdio.h> 
#include <conio.h> 

const   int   M=3; 
const   int   N=4; 
main() 
{ 
int   Matrix[M][N]={1,2,3,4,5,6,7,8,9,10,11,12}; 
int   i=0   ; 
int   j=0   ; 
int   tmpi   =   0; 
int   tmpj   =   0; 
int   u   =   0; 
printf( "原矩阵为:\n "); 
for   (i=   0   ;i <   M   ;i++) 
{ 
for(j=0   ;   j <   N;   j++) 
printf( "     %d     ",Matrix[i][j]); 
printf( "\n "); 
} 
printf( "顺时针转90度后:\n "); 
for   (i=   0   ;i <   N   ;   i++) 
{ 
for(j=   0   ;   j <   M;   j++) 
{ 
//求该交换元素在原矩阵对应的位置 
tmpi   =   M-   j   -1; 
tmpj   =   i   ; 
//循环查找最后交换的位置 
while((tmpi   *   N   +   tmpj)   <     i   *   M     +   j   ) 
{ 
u=   (tmpi   *   N   +   tmpj   ); 
tmpi   =     u     /   M   ; 
tmpj   =     u   %   M   ; //转成N*m矩阵的坐标

tmpi   =   tmpi   +   tmpj; //在转换成原始矩阵的坐标,最终找出最后交换的位置
tmpj   =   tmpi   -   tmpj; 
tmpi   =   tmpi   -   tmpj; 
tmpi   =   (M-tmpi   -1);
 
} 
//交换矩元素,后一个作暂存用 
if   (*(&Matrix[0][0]   +   i   *   M   +   j)   !=   Matrix[tmpi][tmpj]) 
{ 
*(&Matrix[0][0]   +   i   *   M   +   j)   =   *(&Matrix[0][0]   +   i   *   M   +   j) 
+   Matrix[tmpi][tmpj]; 
Matrix[tmpi][tmpj]   =   *(&Matrix[0][0]   +   i   *   M   +   j)   
-   Matrix[tmpi][tmpj]; 
*(&Matrix[0][0]   +   i   *   M   +   j)   =   *(&Matrix[0][0]   +   i   *   M   +   j)   
-   Matrix[tmpi][tmpj]; 
} 

printf( "     %d     ",*(&Matrix[0][0]   +   i   *   M   +   j)); 
} 
printf( "\n "); 
} 
getch(); 
return   0; 
}

原创粉丝点击