1. 程式人生 > >C++多維陣列:儲存方式、訪問方式和作為函式引數

C++多維陣列:儲存方式、訪問方式和作為函式引數

C++中陣列可以巢狀,就是多維陣列。

多維陣列儲存與訪問方式

二維陣列:一維陣列可對應數學中的向量,而二維陣列可對應矩陣,可用一個二維陣列儲存矩陣。


圖1  二維陣列mat示意圖

二維陣列的橫向稱為行,縱向稱為列,上面這個陣列為三行六列。定義二維陣列的通用格式為:
    《儲存型別》 型別 陣列名[常量行表示式] [常量列表達式];
行與列用常量表達式表示。

二維陣列分析:上面的陣列可定義為:
    int mat[3][6];
第一行第一列的元素為mat[0][0],第三行第六列元素為 mat[2][5], 下標仍是從0開始。

計算機記憶體是一維編址的,多維陣列必須要轉化為一維方式儲存,越右的下標變化越快,二維陣列則按行排列,先排第一行,再排第二行,直到所有行排完,即所謂按行排列


mat[0][0] mat[0][1] mat[0][2] mat[0][3] mat[0][4] mat[0][5] mat[1][0] mat[1][1] mat[1][2] mat[1][3] mat[1][4] mat[1][5] mat[2][0] mat[2][1] mat[2][2] mat[2][3] mat[2][4] mat[2][5]

有了確定的關係後可以算出多維陣列任一元素在記憶體的位置。設有a陣列m行n列,每個元素佔b個位元組,a[i][j] 的首地址為:陣列的首地址+(i*n+j)*b;

多維陣列分析:C/C++ 中的多維陣列基本的定義是以陣列作為元素構成的陣列,二維陣列的陣列元素是一維陣列,三維陣列的陣列元素是一個二維陣列,依此類推。也就是說,多維陣列用的是一個巢狀的定義。

多維陣列的陣列名:代表陣列中第一維(最高維)第一個元素(0號元素)在記憶體中的首地址,如三維陣列的陣列名代表的是組成三維陣列的第一個二維陣列的儲存首地址。

當陣列作為函式的引數進行傳遞時,多維陣列同樣是作為第一維第一個陣列的首地址傳遞給函式,所以物理上是傳地址。在函式中對形參的陣列元素的修改實際上是對作為實參的原陣列的元素進行修改。

初始化:
對於二維陣列,可用巢狀一維陣列初始化進行:
    int matrix[3][6]={{1,3,5,7,9,11},{2,4,6,8,10,12},{3,5,7,11,13,17}};
也可以按陣列元素儲存次序列出各元素的值:
    int matrix[3][6]={1,3,5,7,9,11,2,4,6,8,10,12,3,5,7,11,13,17};
還可以對部分元素賦初值,沒有明確初值的元素清0:
    int matrix[3][6]={{1,3},{2,4},{3,5,7}};
其結果等效於:
    int matrix[3][6]={{1,3,0,0,0,0},{2,4,0,0,0,0},{3,5,7,0,0,0}};
最後還可由初始化資料來確定陣列最高維,如
    int matrix[][6]={1,3,5,7,9,11,2,4,6,8,10,12,3,5,7,11,13,17};
結果定義的matrix是三行六列的陣列。也可以
    int matrix[][6]={{1,3},{2,4},{3,5,7}};
同樣也是三行六列。注意這裡只能最高維省略。

多維陣列作為引數:

  • 在作為函式的形式引數時,可以最高維(第一維)省略。因為編譯器只要根據後面每一維(從第二維開始)的大小,就可計算陣列每一個元素的儲存位置。
  • 基於同樣的理由,也只能省略第一維。進一步考慮,對多維陣列,編譯器不檢查邊界,其實只是不檢查最高維(第一維)的邊界,較低各維的大小是在控制之中的。
  • 複合型別只能對各元素逐個操作,不能整體操作。

【例5.4】已知矩陣 int mat[8][8],找出其中的極點與鞍點。如某元素在所在行相鄰點中與所在列相鄰點中均為最大或最小,則為極點;如某元素在所在行(或列)相鄰點中為最大,同時該元素在所在列(或行)相鄰點中為最小,則為鞍點。
#include<iostream>
#include<iomanip>
using namespace std;
int mat[8][8]={0,3,5,7,11,13,17,19,1,2,3,9,16,17,21,18,3,5,4,14,22,19,26,15,5,11,9,6,16,15,
23,12,9,12,8,7,8,9,10,11,7,6,15,14,13,10,9,10,13,4,7,24,20,18,12,12,15,10,9,8,25,19,16,14};
int maxmin(int a,int b,int c){
    if(a>b&&b<c)  return -1;
    else if(a<b&&b>c) return 1;
    else return 0;//b為最大返回1 ,最小返-1,其他為0
}
int main (void){
    int i,j,k,l;
    for(i=1;i<=6;i++)
        for(j=1;j<=6;j++){
            k=maxmin(mat[i][j-1],mat[i][j],mat[i][j+1]);
            if(k==0)  continue;
            l=maxmin(mat[i-1][j],mat[i][j],mat[i+1][j]);
            if(l==0) continue;
            if(k==1&&l==1)
                cout<<"極大點:"<<setw(2)<<mat[i][j]<<" ; i="<<i<<" ; j="<<j<<endl;
            else if(k==-1&&l==-1)
                cout<<"極小點:"<<setw(2)<< mat[i][j]<<" ; i="<<i<<" ; j="<<j<<endl;
            else cout<<"鞍  點:"<<setw(2)<<mat[i][j]<<" ; i="<<i<<" ; j="<<j<<endl;
        }
    return 0;
}

多維陣列作為函式引數

【例5.5】矩陣轉置與矩陣相乘。 下標作為引數傳遞。
#include <iostream>
#include <iomanip>
using namespace std;
void inverse(int [3][6], int [6][3]);
void multi(int [6][3], int [3][4], int [6][4]);
void output(int [6][4]);
int main(){
    int middle[6][3], result[6][4];
    int matrix1[3][6]={8,10,12,23,1,3,5,7,9,2,4,6,34,45,56,2,4,6};  
    int matrix2[3][4]={3,2,1,0,-1,-2,9,8,7,6,5,4};
    inverse(matrix1,middle);
      multi(middle,matrix2,result);
    output(result);
    return 0;
}

void inverse(int matrix1[3][6],int middle[6][3]){           
    int i,j;
    for (i=0;i<3;i++)
      for (j=0;j<6;j++)
        middle[j][i]=matrix1[i][j];                          
    return;                                                     
}
void multi(int middle[6][3],int matrix2[3][4],int result[6][4]){                                                                   
    int i,j,k;
    for (i=0;i<6;i++){
      for (j=0;j<4;j++){
        result[i][j] = 0;
        for (k=0;k<3;k++)
          result[i][j]+=middle[i][k]*matrix2[k][j];
      }
    }
    return;
}
void output(int result[6][4]){
    int i,j;
    cout <<"result"<<'/n';
    for (i=0;i<6;i++){
      for (j=0;j<4;j++)
        cout <<setw(6)<<result[i][j];
      cout<<'/n';
    }
    return;                                                      
}

缺陷與改進:多維陣列作為函式引數,最高維可以不寫,但較低維必須明確標出。這限定了二維陣列的構造,所以用二維陣列進行矩陣運算很難表示成通用的演算法。

既然二維陣列使用一維陣列方式儲存,則用一維陣列加上行列資訊傳遞,可不受陣列構造的限制。