问题描述
蛇形矩阵即使用二维数组完成来回曲折的赋值,举例说明如下所示的形式即为蛇形数组。
算法思想
观察该二维数组,只是可以“人为”的发现它就像一条蛇的形状来回爬行,然而并没有什么卵用,不能明确的站在计算机的角度上来实现这个数组。于是将所有的
下标
列出来便可以得到下述所述的曲线走势。
然后结合第一张图便可以发现
- 数字从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;
如果再仔细一点就可以发现,每次轮回(数字从左下到右上或从右上到左下的递增)的过程中,其行下标与列下标之和是不变的。为了清楚的说明这一点,参考下图。
每条红线所标识的每个下标之和不变,比如下标从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");
}
}
}
}