一.矩阵转置
1.问题呈现:
示例:
2.实现方法
首先我们需要一个·大小可变的二维数组,具体的定义方法请参考:http://t.csdn.cn/3XvSL
代码:
1. int arr[20][20]; 2. int n = 0, m = 0; 3. scanf("%d %d", &n, &m); //输入行和列 4. int i = 0, j = 0; 5. for (i = 0; i < n; i++) //初始化数组 6. { 7. for (j = 0; j < m; j++) 8. { 9. scanf("%d", &arr[i][j]); 10. } 11. }
那具体该怎么实现矩阵转置呢?
从示例中我们可以看出由本来的2行3列经转置后变成了3行2列,且数组中元素的存放内存是连续的,其实转置只是一种视觉效果,数组中元素的内存没有发生改变,只是打印数组的时候呈现的转置的结果。所以我们可以利用这一点解决问题。想要利用内存,我们就需要使用指针来处理,
我们知道数组名表示数组首元素的地址,而二维数组首元素的地址指的是第一行的地址,要想真正使用二维数组的第一个元素的地址,可以这样定义: int *p=&arr[0][0];
下面来看代码:
1. int* p = &arr[0][0]; 2. for (i = 0; i < m; i++) //转置后的矩阵行和列刚好相反 3. { 4. 5. for (j = 0; j < n; j++) 6. { 7. printf("%d ",*(p+i+j*20)); //这里的20就是你之前定义数组的列的大小,不可以写成其他的 8. } 9. printf("\n"); 10. }
如果 *(p+i+j*20)写成 *(p+i+j*m)就会出现这样的结果:
发现第二列的数字很奇怪,这是为什么?
通过监视我们发现1,2,3,4,5,6不是连续存储的,由于定义动态数组的方法是间接的,不能算的是完全意义上的动态数组,所以会出现这种情况。
上面这种打印方式不免有些复杂,且容易出错,下面介绍一种简单的方法:
只需将printf的部分改掉就行了,转置后行和列是相反的,那我们打印的时候行和列也是相反的不就行了,这张方法简洁易懂,且不易出错。
二.蛇形矩阵
1.问题呈现:
2.实现方法:
蛇形矩阵的第一行和最后一列与内部的元素关联性不是特别强,且内部元素的排列富有规律,所以我们先赋值第一行和最后一列,这很简单:
1. int arr[20][20]; 2. int n = 0, i = 0, j = 0,count=1; //count用来记录数字的变化,实现数字的递增 3. scanf("%d", &n); 4. //打印第一行 5. for (j=0; j < n; j++,count++) //count++不能忘记写,不然数据会不对 6. { 7. arr[0][j] = count; 8. } 9. //打印最后一列 10. for (i = 1; i < n; i++,count++) 11. { 12. arr[i][n-1] = count; 13. }
接下来我们只需对数组的n-1行,n-1列进行赋值,所以我们总共循环 n-1 次,注意这里只能选择从最后一行给数组赋值,若是从第二行开始就不符合蛇形矩阵的定义。i要赋值成 i=n-1,才可以从最后一行开始赋值。
那最后一行该怎么正确赋值呢?
仔细观察数字的特点,我们发现是从后往前赋值的,赋值完一行后对上一行进行从前向后赋值,请看具体代码:
1. i = n - 1; //使数组从最后一行开始赋值 2. while (i>0) //控制循环次数 3. { 4. for (j = n - 2; j >= 0; j--,count++) //从后向前赋值 5. { 6. arr[i][j] = count; 7. } 8. i--; //赋值上一行 9. for (j = 0; j <= n - 2; j++, count++) //从前向后赋值 10. { 11. arr[i][j] = count; 12. } 13. i--; //赋值上一行 14. }
注意count++是一直存在的,最关键的部分完成了,之后就是打印数组了,来看完整代码和最终效果:
这里的%3d是为了打印出来的蛇形矩阵更好看,你可以你根据你自己的看法修改。
本篇文章就到这里啦,谢谢你的阅读。
如有错误或者是建议,欢迎小伙伴们指出。
拜拜~