5.2 多维数组

来源:互联网 发布:mac chrome flash插件 编辑:程序博客网 时间:2024/04/29 22:54
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;                                                      
}

缺陷与改进:多维数组作为函数参数,最高维可以不写,但较低维必须明确标出。这限定了二维数组的构造,所以用二维数组进行矩阵运算很难表示成通用的算法。

既然二维数组使用一维数组方式存储,则用一维数组加上行列信息传递,可不受数组构造的限制。
1 0