螺旋矩阵/旋转摆花的两种做法(含方向数组)

 

Ⅰ.运用方向数组(易)

所谓方向数组,即为设置一个一维数组→数组内包含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");
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值