写在前面:可以先看代码2,易于理解整个流程,再看代码1,是市面常规思路。
一、理解题目
从左上角开始的一个从1开始的自然递增序列,按顺时针方向组成方阵。
1. 一目了然
如图所示就是一个5阶的螺旋方阵:
即:需要对一个二维数组,按上述规律赋值,最后打印。
思考:
- 怎么把坐标和递增序列联系起来;
- 在什么时候停止这个递增。
2. 问题一:如何递增?——划分四方向递增
从图像可以看出,顺时针递增的规律,可以划分为4个方向:
假设使用matrix[x][y]存储该方阵,则方向与坐标变化规律如下:
1. 往右递增:x不变,y递增
2. 往下递增:x递增,y不变
3. 往左递增:x不变,y递减
4. 往上递增:x递减,y不变
下面这张图打印出来了坐标:
所以我们就找到了数组下标和递增序列的关系。
继续思考:
1.如何换方向?–单向递增的边界:比如,往右就会有一个右边界
2.换几次方向?–整体递增的边界:比如,1~2阶需一轮顺时针,3~4阶方阵需两轮顺时针
3. 问题二:递增停止?——边界判定
3.1 某方向上的边界
以n=5阶为例:
第一轮循环(i=0),往右时,变化的坐标y为0~4:
在第二轮的时候,坐标就是从1-3
第三轮的时候,坐标只有2了
3.2 整体的边界
- 计轮数:当经过了 n/2[+1] 轮顺时针后表明已经赋值完毕
【原因】:阶数n和轮数m的关系:m是n的中点。
【直观理解】:最后一轮一定在最中间(螺旋,一圈圈往内顺时针转)。观察起点坐标,每一轮增加1.
于是 m = n/2[+1](奇数/2后要+1)
【例如】下面依次为2阶–1轮、3阶–2轮、4阶–2轮
2.直接计数:n阶方阵赋值到n^2直接结束,简单粗暴。
二、代码实现
代码1.直观的代码
轮数很容易确定,因此最外层的循环很容易理解,循环次数就是轮次;
而判断边界的时候就一定要在边界处分析清楚:
以5阶第一轮为例【i=0,n=5】
2.下方向 是第二行开始,坐标为1(i+1)
4.上方向从倒数第二行开始,坐标为3(n-i-2)而不是4。
具体的看代码注释,自行画图理解。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
// 打印螺旋方阵
int matrix[10][10]; // 螺旋矩阵
int k = 1; // 递增数,从1 开始
int i, j; // 循环控制变量,i控制轮数,j控制坐标
int m, n; // m轮数,n阶数
scanf("%d", &n); //输入阶数
if (n%2==0) // 确定轮数
{
m = n / 2;
}
else
{
m = n / 2 + 1;
}
for (i = 0; i < m; i++) //m轮顺时针圈
{
for (j = i; j < n-i; j++) // 1.往右:x = i , y值从i开始递增
{
matrix[i][j] = k++;
}
for ( j = i + 1; j < n - i; j++) //2.往下:注意x从i+1开始递增,即往下挪一位才是下一个数, y = n - i - 1
{
matrix[j][n - i - 1] = k++;
}
for ( j = n-i-2; j >=i; j--) // 3. 往左:x = n - i - 1,y从n-i-2递减
{
matrix[n - i - 1][j] = k++;
}
for (j = n-i-2; j >= i + 1 ; j--) // 4. 往上:x从n-i-2递减到i+1,y = i
{
matrix[j][i] = k++;
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("matrix[%d][%d]: %-5d", i, j, matrix[i][j]);
}
printf("\n");
}
}
代码2. 易于理解的代码
这个思路易于理解,就在于边界的检测不需要进行绕脑的计算;
简单粗暴的进行判断:
1. 首先,左边自然不能超过n,递增到了n时就是越界;
2. 如果我们给螺旋矩阵来一个初值-1,那么遇到任何-1直接赋值,任何非-1,说明此前已经赋值,越界。
螺旋矩阵有一个特点:遇到边界后就换方向递增
因此我们成功判越界,就直接坐标回退+换向即可。
具体见代码文章来源:https://www.toymoban.com/news/detail-713847.html
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int matrix[10][10]; // 螺旋数组
int i, j;
int k = 1; // 从1开始递增
int flag = 1; // 方向,1表示向右,2向下,顺时针类推
int n;
scanf("%d", &n);
// 赋初值-1,从而可以区分边界(遇到不是-1就是越界)
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
matrix[i][j] = -1;
}
}
i = 0; j = 0;
while (k <= n*n) // 赋值n^2个就停止
{
// 非边界,赋值
if (matrix[i][j] == -1)
matrix[i][j] = k++;
// 赋值之后检查方向,以确定变化的坐标,并且进行边界检测
if (flag == 1)
{
j++;//往右就是y坐标递增
// 边界检测,=n或者值不是-1就说明已经越界
if (j == n||matrix[i][j] != -1)
{
j--;
flag = 2; // 碰到边界就换方向
}
}
else if (flag == 2)
{
i++;//往下就是x坐标递增
// 边界检测,=n或者值不是-1就说明已经越界
if (i == n || matrix[i][j] != -1)
{
i--;
flag = 3; // 碰到边界就换方向
}
}
else if (flag == 3)
{
j--;//往左就是y坐标递减
// 边界检测,=n或者值不是-1就说明已经越界
if (j == n || matrix[i][j] != -1)
{
j++;
flag = 4; // 碰到边界就换方向
}
}
else if (flag == 4)
{
i--;//往上就是x坐标递减
// 边界检测,=n或者值不是-1就说明已经越界
if (i == n || matrix[i][j] != -1)
{
i++;
flag = 1; // 碰到边界就换方向
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("matrix[%d][%d]: %-5d", i, j, matrix[i][j]);
}
printf("\n");
}
}
END文章来源地址https://www.toymoban.com/news/detail-713847.html
到了这里,关于螺旋矩阵【直观看懂,C语言代码,两版本】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!