Ⅰ.运用方向数组(易)
所谓方向数组,即为设置一个一维数组→数组内包含0,1,-1,用于改变被赋值数组的处理方向
典例:螺旋矩阵
以下为 ①行改变方向数组 dx[4]={0,1,0,-1}
②列改变方向数组 dy[4]={-1,0,1,0}
③被赋值数组 a[x][y]
如何使用方向数组改变数组的处理方向呢?
比如:
#include <stdio.h>
int main()
{
int x = 0, y = 0, k = 1;
char a[1000][1000] = { 0 };
int dx[4] = { 0,1,0,-1 };
int dy[4] = { -1,0,1,0 };
int n, i, j;
scanf("%d", &n);
for (i = 0; i < n * n; i++)
{
a[x][y] = 'A' + i % 26; //数组赋值等等
x += dx[k], y += dy[k];
if (x < 0 || y < 0 || x >= n || y >= n || a[x][y] != 0) //越界与碰壁
{
x -= dx[k];
y -= dy[k];
k = (k + 1) % 4; //改变处理方向(改变引用方向数组元素的位置)
x += dx[k];
y += dy[k];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++) printf("%c", a[i][j]);
printf("\n");
}
}
越界:即为超出数组在题目中n行n列的范围
碰壁:在处理数组元素的时候,又一次碰到之前处理过的元素
我们以n=4为例,(x,y)x表示数组的行,y表示列来演示越界与碰壁
过程为:
x+=dx[k],y+=dy[k];其中k的初始值为1
则(0.0)→ (1.0) →(2.0)→ (3.0) →(4.0)【越界】
进入if语句:(4.0)→(3.0) k=2;此时dx[k]=0,dy[k]=1
(3.0)→(3.1)→(3.2)→(3.3)→(3.4)【越界】
进入if语句:(3.4)→(3.3) k=3;此时dx[k]=-1,dy[k]=0
(3.3)→(2.3)→(1.3)→(0.3)→(-1.3)【越界】
进入if语句:(-1.3)→(0.3)k=(3+1)%4=10;此时dx[k]=0,dy[k]=-1
(0.3)→(0.2)→(0.1)→(0.0)【碰壁】
进入if语句............
并以此类推
经过方向数组的运用,我们可以通过仅仅改变方向数组的内容,来实现对螺旋矩阵不同方向的处理
无论是逆时针,还是顺时针,或者是改变起始位置的情况下,运用方向数组都可以更加轻松的完成
上方的代码是以a[0][0]为起始,起始处理方向为:向下↓ 进行的逆时针赋值
若我们要将起始处理方向改为:向右→ 进行顺时针赋值
则将方向数组改变为
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };即可
Ⅱ.写出4个方向的赋值过程并且组成循环
概念介绍:
①循环不变量:指对于循环处理,其规律应该相同,防止出现溢出等等情况
②偏移量offset:每一次完整循环,条件数值上带来的偏移
③循环不变原则:每一次进入循环,都要保持处理规律不变
对于螺旋矩阵的规律,我们要用
〇 → 的形式 进行 一圈式的赋值循环
↑ ↓
←
为了创造出此类图案,并且赋值,我们需要用到二维数组
关于二维数组我们要了解 a[x][y]中x表示行,y表示列
在C语言中二维数组是按照行来存放的 意思就是说 一行放y列,一共x行
也就是 y1 y2 y3 y4 y5
x1{ 1 , 2 , 3 , 4 , 5 }
x2{ 6 , 7 , 8 , 9 , 10 }
所以对于a[x][y]的赋值,就应该一行赋完再换行→意味着a[x][y]的循环应该是y++赋值
for (; y < sty + n - offset; y++) a[x][y] = num++;
不过对着列赋值同样也是可以的
for (; x < stx + n - offset; x++) a[x][y] = num++;
针对循环不变原则,当我们要处理每一条边的时候,都要保持处理规律不变
那么处理模式就可以是 左闭右开 [....) 或者 右闭左开(...]
即 处理一边上的数组元素,但不处理作为下一边开头的数组元素
0→ 1→丨(阻断) 2 这样每一条边如此处理,当完成4边的时候正好形成一个闭环
对于偏移量的模糊了解是致命的:起点〇→→offset丨→n 每完成一圈,左右上下边界减小,整体向内缩小一个单位
若按照单个边来算,一条边缩进2个单位,所以每次结束一圈的循环,offset+=2;其中offset的默认值要为1
所以 前两边的循环条件就有:y我们假定n=3,starty=0则 yy
所以对于无法赋值的奇数情况下的中间值
我们则要单独进行赋值a[mid][mid]=num++;
标准做法
#include <stdio.h>
int main() {
char ans[1000][1000];
int n;
scanf_s("%d", &n);
int i, j;
//设置每次循环的起始位置
int startX = 0;
int startY = 0;
//设置二维数组的中间值,若n为奇数。需要最后在中间填入数字
int mid = n / 2;
//循环圈数
int loop = n / 2;
//偏移数
int offset = 1;
//当前要添加的元素
int count = 0,num=90;
while (loop) {
i = startX;
j = startY;
//模拟上侧从左到右
for (; j < startY + n - offset; j++) {
ans[startX][j] = num-(count++)%26;
}
//模拟右侧从上到下
for (; i < startX + n - offset; i++) {
ans[i][j] = num - (count++) % 26;
}
//模拟下侧从右到左
for (; j > startY; j--) {
ans[i][j] = num - (count++) % 26;
}
//模拟左侧从下到上
for (; i > startX; i--) {
ans[i][j] = num - (count++) % 26;
}
//偏移值每次加2
offset += 2;
//遍历起始位置每次+1
startX++;
startY++;
loop--;
}
//若n为奇数需要单独给矩阵中间赋值
if (n % 2)
ans[mid][mid] = num - (count++) % 26;
for(i = 0; i < n; i++) {
for (j = 0; j < n; j++) printf(" %c", ans[i][j]);
printf("\n");
}
}