標籤:
問題描述
蛇形矩陣即使用二維數組完成來回曲折的賦值,舉例說明如下所示的形式即為蛇形數組。
演算法思想
觀察該二維數組,只是可以“人為”的發現它就像一條蛇的形狀來回爬行,然而並沒有什麼卵用,不能明確的站在電腦的角度上來實現這個數組。於是將所有的下標列出來便可以得到下述所述的曲線走勢。
然後結合第一張圖便可以發現
- 數字從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 5void 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"); } } }}
第3章第1節練習題1 蛇形矩陣