第3章第1节练习题1 蛇形矩阵

问题描述

蛇形矩阵即使用二维数组完成来回曲折的赋值,举例说明如下所示的形式即为蛇形数组。

Snack

算法思想

观察该二维数组,只是可以“人为”的发现它就像一条蛇的形状来回爬行,然而并没有什么卵用,不能明确的站在计算机的角度上来实现这个数组。于是将所有的下标列出来便可以得到下述所述的曲线走势。

Sanck

然后结合第一张图便可以发现

  • 数字从2~3的过程中,下标行变化范围是0~1;下标列范围是1~0;
  • 数字从4~6的过程中,下标行变化范围是2~0;下标列范围是0~2;
  • 数字从7~10的过程中,下标行变化范围是0~3;下标列范围是3~0;
  • 数字从11~15的过程中,下标行变化范围是4~0;下标列范围是0~4;

  • 数字从16~19的过程中,下标行变化范围是1~4;下标列范围是4~1;
  • 数字从20~22的过程中,下标行变化范围是4~2;下标列范围是2~4;
  • 数字从23~24的过程中,下标行变化范围是3~4;下标列范围是4~3;

如果再仔细一点就可以发现,每次轮回(数字从左下到右上或从右上到左下的递增)的过程中,其行下标与列下标之和是不变的。为了清楚的说明这一点,参考下图。

Snack

每条红线所标识的每个下标之和不变,比如下标从01变为10(注:这里的10意思是(1, 0)即元素下标,后面同理),其行下标与列下标之和为1;在比如下标从20变为11在变为02的过程中,行下标与列下标之和为2;依次类推。为了方便表示,沿主对角线方向画一条绿色的线,该线与红线的交点表示每条红线中的每个元素所代表的行下标与列下标之和。

使用(i,j)表示每个元素的下标,使用k表示沿绿线方向的每个元素的下标之和,这样每个元素的下标便可以表示为(i,k-i);

但应该注意到副对角线上下部分下标的变化方式不同,在副对角线上半部分,行下标和列下标最小值为0,最大值依次递增;而副对角线下半部分,行下标和列下标的最大值为4,而最小值递增。

算法描述

void SnackArray(int A[][N]){
    int cnt=0;
    //副对角线上半部分
    for(int k=0;k!=N;k++){
        if(k%2==0){
            //从左下到右上
            for(int i=k;i>=0;i--){
                A[i][k-i]=++cnt;
            }
        }else{
            //从右上到左下
            for(int i=0;i<=k;i++){
                A[i][k-i]=++cnt;
            }
        }
    }
    //副对角线下半部分
    for(int k=N;k<2*N-1;k++){
        if(k%2==0){
            //从左下到右上
            for(int i=N-1;i>=k-N+1;i--){
                A[i][k-i]=++cnt;
            }
        }else{
            //从右上到左下
            for(int i=k-N+1;i<=N-1;i++){
                A[i][k-i]=++cnt;
            }
        }
    }
}

具体代码见附件。


附件

#include<stdio.h>
#define N 5

void SnackArray(int (*)[N]);
void Show(int (*)[N]);

int main(int argc,char* argv[]){
    int Arry[N][N]={{0}};
    SnackArray(Arry);
    Show(Arry);
    return 0;
}

//蛇形数组赋值
void SnackArray(int A[][N]){
    int cnt=0;
    for(int k=0;k!=N;k++){
        if(k%2==0){
            for(int i=k;i>=0;i--){
                A[i][k-i]=++cnt;
            }
        }else{
            for(int i=0;i<=k;i++){
                A[i][k-i]=++cnt;
            }
        }
    }
    for(int k=N;k<2*N-1;k++){
        if(k%2==0){
            for(int i=N-1;i>=k-N+1;i--){
                A[i][k-i]=++cnt;
            }
        }else{
            for(int i=k-N+1;i<=N-1;i++){
                A[i][k-i]=++cnt;
            }
        }
    }
}

//打印蛇形数组
void Show(int A[][N]){
    for(int i=0;i!=N;i++){
        for(int j=0;j!=N;j++){
            printf("%5d",A[i][j]);
            if(j==N-1){
                printf("\n");
            }
        }
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值