《艾爾登法環》法術價效比一覽 法師推圖法術推薦

二維陣列
一、二維陣列的定義
當一維陣列元素的型別也是一維陣列時,便構成了“陣列的陣列”,即二維陣列。二維陣列定義的一般格式:
資料型別 陣列名[常量表達式1] [常量表達式2] ;
例如:int a[4][10];
a陣列實質上是一個有4行、10列的表格,表格中可儲存40個元素。第1行第1列對應a陣列的a[0][0],第n行第m列對應陣列元素a[n-1][m-1]。
說明:當定義的陣列下標有多個時,我們稱為多維陣列,下標的個數並不侷限在一個或二個,可以任意多個,如定義一個三維陣列a和四維陣列b:
int a[100][3][5];
int b[100][100][3][5];
多維的陣列引用賦值等操作與二維陣列類似。
二、二維陣列元素的引用
二維陣列的陣列元素引用與一維陣列元素引用類似,區別在於二維陣列元素的引用必須給出兩個下標。
引用的格式為:
<陣列名>[下標1][下標2]
說明:顯然,每個下標表達式取值不應超出下標所指定的範圍,否則會導致致命的越界錯誤。
例如,設有定義:int a[3][5];
則表示a是二維陣列(相當於一個3*5的表格),共有3*5=15個元素,它們是:
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]
因此可以看成一個矩陣(表格),a[2][3]即表示第3行第4列的元素。
三、二維陣列的初始化
二維陣列的初始化和一維陣列類似。可以將每一行分開來寫在各自的括號裡,也可以把所有資料寫在一個括號裡。
例如:
int direct[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}
int direct[4][2] = {1,0,0,1,-1,0,0,-1} //儘量不要用
四、二維陣列程式設計
例5.8 設有一程式

#include<cstdio>

#include<iostream>

#include<iomanip>

const int n=3;

namespace" title="using namespace">using namespace std;

int a[n+1][n+1];

int main()

{

for (int i=1; i<=n; ++i)

{

for (int j=1; j<=n; ++j)

cin>>a[i][j];

}

for (int i=1; i<=n; ++i)

{

for (int j=1; j<=n; ++j)

cout<<setw(5)<<a[j][i];

cout<<endl;

}

return 0;

}

程式的輸入:

2 1 3
3 3 1
1 2 1
程式的輸出:
2 3 1
1 3 2
3 1 1
例5.9 已知一個6*6的矩陣(方陣),把矩陣二條對角線上的元素值加上10,然後輸出這個新矩陣。
【分析】 矩陣即表格,是一個二維陣列,有6行6列共36個元素,每個矩陣都有二條對角線,本題難點在於對角線的元素怎麼確定。

#include<iostream>

#include<iomanip>

using namespace std;

int a[7][7];

int main()

{

   for (int i=1; i<=6; ++i) //輸入矩陣元素

   for (int j=1; j<=6; ++j)

   cin>>a[i][j];

   for (int i=1; i<=6; ++i) //更改對角線上元素的值

   for (int j=1; j<=6; ++j)

   if ((i==j)||(i+j==7)) a[i][j]+=10; //尋找對角線的特徵

   for (int i=1; i<=6; ++i) //輸出6行6列的矩陣元素

   {

   for (int j=1; j<=6; ++j)

   cout<<setw(5)<<a[i][j];

   cout<<endl;

   }

   return 0;

}

例5.10 大部分元素是0的矩陣稱為稀疏矩陣,假設有k個非0元素,則可把稀疏矩陣用K*3的矩陣簡記之,其中第一列是行號,第二列是列號,第三列是該行、該列下的非0元素的值。如:

0 0 0 5 寫簡記成: 1 4 5 //第1行第4列有個數是5
0 2 0 0 2 2 2 //第2行第2列有個數是2
0 1 0 0 3 2 1 //第3行第2列有個數是1
試程式設計讀入一稀疏矩陣,轉換成簡記形式,並輸出。
【分析】 本題中需要解決的主要問題是查詢非零元素並記憶位置。將原始矩陣存於陣列a。轉換後的矩陣存於陣列b,當然b陣列的行數可以控制在一個小範圍內。

#include<iostream>

#include<iomanip>

const int n=3,m=5;

using namespace std;

int main()

{

    int a[n+1][m+1],b[101][4],k=0;

    for (int i=1; i<=n; ++i) //矩陣初始

    for (int j=1; j<=m; ++j)

    cin>>a[i][j];

    for (int i=1; i<=n; ++i)

    for (int j=1; j<=m; ++j)

    if (a[i][j]!=0) //找到非零值,儲存

    {

    ++k;

    b[k][1]=i;

    b[k][2]=j;

    b[k][3]=a[i][j];

    }

 for (int i=1; i<=k; ++i) //輸出

    {

    for (int j=1; j<=3; ++j)

cout<<setw(3)<<b[i][j];

    cout<<endl;

    }

    return 0;

}

執行結果:

輸入: 0 0 0 0 5
    0 0 4 0 0
    1 0 0 0 1

輸出: 1 5 5
2 3 4
    3 1 1
    3 5 1
例5.11 列印楊輝三角形的前10行。楊輝三角形如下圖:

1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
[圖5-1]         
【問題分析】觀察圖5-1,大家不容易找到規律,但是如果將它轉化為圖5-2,不難發現楊輝三角形其實就是一個二維表的小三角形部分,假設通過二維陣列yh儲存,每行首尾元素為1,且其中任意一個非首位元素yh[i][j]的值其實就是yh[i-1][j-1]與yh[i-1][j]的和,另外每一行的元素個數剛好等於行數。有了陣列元素的值,要列印楊輝三角形,只需要控制好輸出起始位置就行了。

#include<iostream>

#include<iomanip>

using namespace std;

int main()

{

  int a[11][11];

   a[1][1]=1; //設定第一行的值

  for (int i=2; i<=10; ++i) //從第二行開始推

 

  a[i][1]=1; a[i][i]=1; //設定每一行的首尾值為1

  for (int j=2; j<=i-1; ++j) //當前行非首尾的數

  a[i][j]=a[i-1][j-1]+a[i-1][j]; //每個數等於上一行的二個數之和

  }

  for (int i=1; i<=10; i++)

  {

  if (i!=10) cout<<setw(30-3*i)<<" "; //控制每行的起始位置,即空格數量

  for (int j=1; j<=i; j++) cout<<setw(6)<<a[i][j];

  cout<<endl;

  }

  return 0;

}

例5.12 輸入一串字元,字元個數不超過100,且以“.”結束。 判斷它們是否構成迴文。

【分析】所謂迴文指從左到右和從右到左讀一串字元的值是一樣的,如12321,ABCBA,AA等。先讀入要判斷的一串字元(放入陣列letter中),並記住這串字元的長度,然後首尾字元比較,並不斷向中間靠攏,就可以判斷出是否為迴文。
程式如下:

#include<iostream>

using namespace std;

int main()

{ char ch,letter[101];

int i=0,j=1;

cout<<"Input a string:";

cin>>ch;

while (ch!='.') //讀入一個字串以'.'號結束

{

++i;

letter[i]=ch;

cin>>ch;

}

while ((j<i)&&(letter[j]==letter[i])) //判斷它是否是迴文

{

--i; ++j;

}

if (j>=i) cout<<"Yes"<<endl;

else cout<<"No"<<endl;

return 0;

}

例5.13 蛇形填數

  在n*n方陣裡填入1,2,3,…,n*n,要求填成蛇形。例如n=4時方陣為:
  10 11 12 1
  9 16 13 2
  8 15 14 3
  7 6 5 4
  上面的方陣中,多餘的空格只是為了便於觀察規律,不必嚴格輸出,n<=8。
【分析】:
  類比數學中的矩陣,我們可以用一個所謂的二維陣列來儲存題目中的方陣。只需宣告一個int a[MAXN][MAXN],就可以獲得一個大小為MAXN×MAXN的方陣。在宣告時,兩維的大小不必相同,因此也可以宣告int a[30][50]這樣的陣列,第一維下標範圍是0,1,2,…,29,第二維下標範圍是0,1,2,…,49。
讓我們從1開始依次填寫。設“筆”的座標為(x,y),則一開始x=0,y=n-1,即第0行,第n-1列(別忘了行列的範圍是0到n-1,沒有第n列)。“筆”的移動軌跡是:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上。總之,先是下,到不能填了為止,然後是左,接著是上,最後是右。“不能填”是指再走就出界(例如4→5),或者再走就要走到以前填過的格子(例如12→13)。如果我們把所有格子初始為0,就能很方便地加以判斷。

二維陣列

例5.13 蛇形填數

  在n*n方陣裡填入1,2,3,…,n*n,要求填成蛇形。例如n=4時方陣為:

  10 11 12 1

  9 16 13 2

  8 15 14 3

  7 6 5 4

  上面的方陣中,多餘的空格只是為了便於觀察規律,不必嚴格輸出,n<=8。

【分析】:

  類比數學中的矩陣,我們可以用一個所謂的二維陣列來儲存題目中的方陣。只需宣告一個int a[MAXN][MAXN],就可以獲得一個大小為MAXN×MAXN的方陣。在宣告時,兩維的大小不必相同,因此也可以宣告int a[30][50]這樣的陣列,第一維下標範圍是0,1,2,…,29,第二維下標範圍是0,1,2,…,49。

讓我們從1開始依次填寫。設“筆”的座標為(x,y),則一開始x=0,y=n-1,即第0行,第n-1列(別忘了行列的範圍是0到n-1,沒有第n列)。“筆”的移動軌跡是:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上。總之,先是下,到不能填了為止,然後是左,接著是上,最後是右。“不能填”是指再走就出界(例如4→5),或者再走就要走到以前填過的格子(例如12→13)。如果我們把所有格子初始為0,就能很方便地加以判斷。

#include<cstdio>

#include<cstring>

#define MAXN 10

int a[MAXN][MAXN];

int main()

{

int n,x,y,tot=0;

scanf("%d",&n);

memset(a,0,sizeof(a));

tot=a[x=0][y=n-1]=1;

while (tot<n*n)

{

while (x+1<n && !a[x+1][y]) a[++x][y]=++tot;

while (y-1>=0 && !a[x][y-1]) a[x][--y]=++tot;

while (x-1>=0 && !a[x-1][y]) a[--x][y]=++tot;

while (y+1<n && !a[x][y+1]) a[x][++y]=++tot;

}

for(x=0;x<n;++x)

{

for (y=0;y<n;++y) printf("%3d",a[x][y]);

printf("\n");

}

return 0;

}

【說明】:

這段程式充分利用了C++語言簡潔的優勢。首先,賦值x=0和y=n-1後馬上要把它們作為a陣列的下標,因此可以合併完成;tot和a[0][n-1]都要賦值1,也可以合併完成。這樣,我們用一條語句完成了多件事情,而且並沒有犧牲程式的可讀性,這段程式碼的含義顯而易見。
那4條while語句有些難懂,不過十分相似,因此只需介紹其中的第一條:不斷向下走,並且填數。我們的原則是:先判斷,再移動,而不是走一步以後發現越界了再退回來。這樣,我們需要進行“預判”,即是否越界,以及如果繼續往下走會不會到達一個已經填過的格子。越界只需判斷x+1<n,因為y值並沒有修改;下一個格子是(x+1,y),因此只需a[x+1][y]==0,簡寫成!a[x+1][y](其中!是“邏輯非”運算子)。
細心的讀者也許會發現這裡的一個“潛在bug”;如果越界,x+1會等於n,a[x+1][y]將訪問非法記憶體!幸運的是,這樣的擔心是不必要的。&&是短路運算子。如果x+1<n為假,將不會計算!a[x+1][y],也就不會越界了。
至於為什麼是++tot而不是tot++,留給讀者思考。

 

以上是 《艾爾登法環》法術價效比一覽 法師推圖法術推薦 的全部内容, 来源链接: utcz.com/yxgl/577169.html

回到顶部