目录
一、背景与感想
在我第一次听说回型矩阵的时候,我是懵逼的,因为我此前根本没听过,于是我上网查询了相关资料,然后稍作了解后,我又不屑一顾,感觉也不过如此,然而在我真正上手编程之后,我才感受到回型矩阵真正的魅力。
我觉得,回型矩阵体现的是一种有规律的代码结构,它近乎是一种回环的建筑与自然之美。
二、概念
首先,不要嫌弃我的图丑(笑),因为条件实在有限(哭)
其次,回型矩阵简单来说正是如图所示的回型结构(从1开始回型赋值),它大多存储在一个二维数组里
三、思路
我么们要实现回型的结构,其实就是不断缩小矩形的大小,所以我们定义了四个变量:top,bottom,left,right,分别代表矩形的顶部,底部,左边,右边
然后,我们需要实现赋值,那么就需要一个在矩形大小不变的情况下能进行变化的量,所以我们需要再定义四个变量(其实一个也可以,不过这里为了便于理解用了四个)t,b,L(大写是为了防止l与1搞混),r.
好了,那么我们开始赋值的过程:
当我们的L大于right的时候,停止顶部赋值,并令top++,如此一来便实现了赋值与矩形的缩小
而接下来,我们只需要重复类似的过程就好,需要变的只是变量的名字,所以我说体现了一种有规律的代码结构
最后当top==bottom && left==right时,则赋值结束
感觉怎么样,似乎,,,也不是很难对吧,嘿嘿,那么我们开始愉快地编程吧
四、编程时间
这一部分我们依旧以错误的形式一步步推进
Wrong 1
首先来看我的代码:
#include<stdio.h>
int main() {
int a[30][30];//暂定为一个小型矩阵,所以二维数组小一点
int n = 0;//用户输入矩阵边长
scanf("%d", &n);
int top = 0, bottom, left = 0, right,//矩形大小
L = 0, r, t, b;//四个赋值用的变量
int count = 1;//用于从1开始赋值
bottom = n - 1; right = n - 1;
while (!(top == bottom && left == right)) {//回型赋值//Wrong 1
while (L <= right) {
a[top][L] = count;
count++;
L++;
}
top++; t = top;
while (t <= bottom) {
a[t][right] = count;
count++;
t++;
}
right--; r = right;
while (r >= left) {
a[bottom][r] = count;
count++;
r--;
}
bottom--; b = bottom;
while (b >= top) {
a[b][left] = count;
count++;
b--;
}
left++; L = left;
}
for (int i = 0; i < n; i++) {//遍历输出
for (int j = 0; j < n; j++) {
printf("%-3d ", a[i][j]);
}
printf("\n");
}
return 0;
}
而运行结果是:
很明显,这是一个数组越位,至于为什么,其实是因为这是一个死循环,要使循环停止可不是简简单单 !(top == bottom && left == right)而已,我们来看原因:
照我们的代码来看,当最后一个位置被赋值之后其实情况变成了这样:
所以跳出循环的条件根本不可能达成,因为两直线相交后只会越走越远,错过了就是错过了
so,不分开不就好了(滑稽),那么我们判定一下,当赋值完成(count>n*n)后,我们停止矩形大小(top,bottom,left,right)的变化
那么错误1修正后的代码我们与错误2一并展示
Wrong 2
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
int a[30][30];//暂定为一个小型矩阵,所以二维数组小一点
int n = 0;//用户输入矩阵边长
scanf("%d", &n);
int top = 0, bottom, left = 0, right,//矩形大小
L = 0, r, t, b;//四个赋值用的变量
int count = 1;//用于从1开始赋值
bottom = n - 1; right = n - 1;
while (!(top == bottom && left == right)) {//回型赋值
while (L <= right) {
a[top][L] = count;
count++;
L++;
}
if (count <= n * n) { top++; t = top; }
while (t <= bottom) {
a[t][right] = count;
count++;
t++;
}
if (count <= n * n) { right--; r = right; }
while (r >= left) {
a[bottom][r] = count;
count++;
r--;
}
if (count <= n * n) { bottom--; b = bottom; }
while (b >= top) {
a[b][left] = count;
count++;
b--;
}
if (count <= n * n) { left++; L = left; }
}
//Wrong 2
for (int i = 0; i < n; i++) {//遍历输出
for (int j = 0; j < n; j++) {
printf("%-3d ", a[i][j]);
}
printf("\n");
}
return 0;
}
让我们运行一下n=4的情况:
嗯,很完美
但别高兴的太早!
看看单数的情况:
完蛋,,,BUG又来了
为什么??我们分析一下单数吧:
不难看出,在最后一步之前就形成了top == bottom && left == right的形式,且刚好一个大while循环结束(这很关键!)所以最后一项未成功赋值
那么我们手动赋值一下吧~
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
int a[30][30];//暂定为一个小型矩阵,所以二维数组小一点
int n = 0;//用户输入矩阵边长
scanf("%d", &n);
int top = 0, bottom, left = 0, right,//矩形大小
L = 0, r, t, b;//四个赋值用的变量
int count = 1;//用于从1开始赋值
bottom = n - 1; right = n - 1;
while (!(top == bottom && left == right)) {//回型赋值
while (L <= right) {
a[top][L] = count;
count++;
L++;
}
if (count <= n * n) { top++; t = top; }
while (t <= bottom) {
a[t][right] = count;
count++;
t++;
}
if (count <= n * n) { right--; r = right; }
while (r >= left) {
a[bottom][r] = count;
count++;
r--;
}
if (count <= n * n) { bottom--; b = bottom; }
while (b >= top) {
a[b][left] = count;
count++;
b--;
}
if (count <= n * n) { left++; L = left; }
}
a[top][left] = count; //手动为最后一项赋值//Wrong 3
for (int i = 0; i < n; i++) {//遍历输出
for (int j = 0; j < n; j++) {
printf("%-3d ", a[i][j]);
}
printf("\n");
}
return 0;
}
运行一下吧:
很好,这样最后一项就妥了
但这也带来了Wrong 3。。。
Wrong 3
如果我们回归到n为偶数的情况会如何呢?
很遗憾,因为偶数在循环内就完成了最后一项赋值,所以最后反而画蛇添足了
所以我们进行最后一项赋值时,不如判断一下n的奇偶,再做赋值
又考虑到代码堆在main函数里太臃肿,所以我们把回型赋值包装成一个函数拿出来
这就完了?其实并没有。万万没想到,最后打败我的是n<2的情况。。
Wrong 4
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void return_matrix(int a[][30], int n) {
int top = 0, bottom, left = 0, right,//矩形大小
L = 0, r, t, b;//四个赋值用的变量
int count = 1;//用于从1开始赋值
bottom = n - 1; right = n - 1;
while (!(top == bottom && left == right)) {//回型赋值
while (L <= right) {
a[top][L] = count;
count++;
L++;
}
if (count <= n * n) { top++; t = top; }
while (t <= bottom) {
a[t][right] = count;
count++;
t++;
}
if (count <= n * n) { right--; r = right; }
while (r >= left) {
a[bottom][r] = count;
count++;
r--;
}
if (count <= n * n) { bottom--; b = bottom; }
while (b >= top) {
a[b][left] = count;
count++;
b--;
}
if (count <= n * n) { left++; L = left; }
}
if (n % 2 != 0) { a[top][left] = count; }//对n为单数的情况进行最后一项的赋值
}
int main() {
int a[30][30];//暂定为一个小型矩阵,所以二维数组小一点
int n = 0;//用户输入矩阵边长
scanf("%d", &n);
return_matrix(a, n);
for (int i = 0; i < n; i++) {//遍历输出
for (int j = 0; j < n; j++) {
printf("%-3d ", a[i][j]);
}
printf("\n");
}
return 0;
}
运行一下:
很完美,如果没有下面这个。。。
摆烂了,直接面向结果编程:看看最终代码吧:
四、最终代码
#include<stdio.h>
void return_matrix(int a[][30], int n) {
int top = 0, bottom, left = 0, right,//矩形大小
L = 0, r, t, b;//四个赋值用的变量
int count = 1;//用于从1开始赋值
bottom = n - 1; right = n - 1;
if(n==2){
a[0][0]=1;
a[0][1]=2;
a[1][0]=4;
a[1][1]=3;
}
else if(n==1) a[0][0]=1;
else {
while (!(top == bottom && left == right)) {//回型赋值
while (L <= right) {
a[top][L] = count;
count++;
L++;
}
if (count <= n * n) { top++; t = top; }
while (t <= bottom) {
a[t][right] = count;
count++;
t++;
}
if (count <= n * n) { right--; r = right; }
while (r >= left) {
a[bottom][r] = count;
count++;
r--;
}
if (count <= n * n) { bottom--; b = bottom; }
while (b >= top) {
a[b][left] = count;
count++;
b--;
}
if (count <= n * n) { left++; L = left; }
}
if (n % 2 != 0) { a[top][left] = count; }
}//对n为单数的情况进行最后一项的赋值
}
int main() {
int a[30][30];//暂定为一个小型矩阵,所以二维数组小一点
int n = 0;//用户输入矩阵边长
scanf("%d", &n);
return_matrix(a, n);
for (int i = 0; i < n; i++) {//遍历输出
int j;
for (j = 0; j < n-1; j++) {
printf("%03d ", a[i][j]);
}
printf("%03d\n", a[i][j]);
}
return 0;
}
运行一下(稍微改了下输出格式):
感谢观看~