BDS之数组与矩阵

来源:互联网 发布:人工智能行动计划 编辑:程序博客网 时间:2024/05/18 03:07

数组

数组是将相同数据类型的元素按照一定顺序排列而成的集合。由于存储单元是一维结构,而数据是多维的结构,则用一组连续存储单元存放数组元素就有个次序约定问题,这也就是数组结构产生的原因。

下面我们看下简单的数组是如何实现的:

#define MAX_ARRAY_DIM  8#define ERROR -1#define OK   0#define UNDERFLOW 4#define OVERFLOW  -2typedef int Status;struct Array{ElemType* base; //数组元素基址 int dim;  //数组维数int *bounds; //数组维界基址int *constants;//数组映像函数常量基址};//init arrayStatus init_array(Array &A,int dim,...){int elemtotal = 1,i;va_list ap;if(dim<1 || dim>MAX_ARRAY_DIM)return ERROR;A.dim = dim;A.bounds = (int*)malloc(dim*sizeof(int));if(!A.bounds)return ERROR;va_start(ap,dim);for(i=0;i<dim;i++){A.bounds[i] = va_arg(ap,int);if(A.bounds[i]<0)return UNDERFLOW;elemtotal *=A.bounds[i];}va_end(ap);A.base = (ElemType*)malloc(elemtotal*sizeof(ElemType));if(!A.base)return ERROR;A.constants = (int*)malloc(dim*sizeof(int));if(!A.constants)return ERROR;A.constants[dim-1] = 1;for(i=dim-2;i>=0;i--)A.constants[i]= A.constants[i+1]*A.bounds[i+1];return OK;}void destroy_array(Array &A){if(A.base)free(A.base);if(A.bounds)free(A.bounds);if(A.constants)free(A.constants);A.base = A.bounds = A.constants = NULL;A.dim = 0;}Status locate(Array A,va_list ap,int &off){int i,idx ;off = 0;return OK;}Status value(ElemType &e,Array A,...){va_list ap;int i,off=0,idx;va_start(ap,A);for(i = 0;i<A.dim ;i++){idx = va_arg(ap,int);if(idx<0 || idx >=A.bounds[i])return ERROR;off += A.constants[i]*idx;}e = *(A.base+off);return OK;}Status assign(Array &A,ElemType e,...){va_list ap;int i,idx,off=0;va_start(ap,e);for(i = 0;i<A.dim ;i++){idx = va_arg(ap,int);if(idx<0 || idx >=A.bounds[i])return ERROR;off += A.constants[i]*idx;}*(A.base+off)=e;return OK;}

我们知道数组支持随机存储访问,那么对于数组结构,访问元素的形式才是需要关注的重点,对于一个n维的矩阵,每一维大小为b1,b2,...bn,那么如果给定索引j1,j2,...jn,那么要取得该元素,就需要求其在数组存储单元中的偏移量LOC[j1,j2,...jn]为


矩阵

矩阵是一个数学概念,但是它在计算机中的表现形式是基于二维数组的。这里我们主要关注稀疏矩阵,所谓稀疏矩阵是指在矩阵中非零元素较少,且分布没有规律。更为准确的描述是假设m×n的矩阵中,有t个元素不为零。令δ=t/(m×n),称δ为矩阵的稀疏因子,通常认为δ<=0.05时称为稀疏矩阵。

下面是基于三元组顺序表的稀疏矩阵压缩存储方式:

typedef int Status ;#define ERROR -1;#define OK  0;//稀疏矩阵的三元组顺序表存储结构#define MAX_SIZE  100 struct Triple{int i,j;//行、列索引ElemType e;};struct TSMatrix{Triple data[MAX_SIZE+1];//data[0]未用int mu,nu,tu;//行数、列数、非零元素数};Status create_matrix(TSMatrix &M){int i;Triple T;Status k;printf("请输入矩阵的行数、列数以及非零元素个数:");scanf("%d,%d,%d",&M.mu,&M.nu,&M.tu);if(M.tu>MAX_SIZE)return ERROR;M.data[0].i = 0;for(i=1;i<=M.tu;i++){do{printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:",i,M.mu,M.nu);scanf("%d,%d,%d",&T.i,&T.j,&T.e);k=0;if(T.i<1 || T.i>M.mu || T.j<1 || T.j>M.nu)k=1;if(T.i<M.data[i-1].i || T.i==M.data[i-1].i &&T.j<=M.data[i-1].j)k=1;}while(k);M.data[i]=T;}return OK;}int comp(int c1,int c2){if(c1<c2)return -1;if(c1==c2)return 0 ;return 1;}Status add_matrix(TSMatrix M,TSMatrix N,TSMatrix &Q){int m=1,n=1,q=0;if(M.mu!=N.mu || M.nu!=N.nu)return ERROR;Q.mu=M.mu;Q.nu=M.nu;while(m<=M.tu && n<=N.tu){switch(comp(M.data[m].i,N.data[n].i)){case -1:Q.data[++q]=M.data[m++];break;case 0:switch(comp(M.data[m].j,N.data[n].j)){case -1: Q.data[++q]=M.data[m++];break;case 0 :Q.data[++q]=M.data[m++];Q.data[q].e +=N.data[n++].e;if(Q.data[q].e==0)q--;break;case 1:Q.data[++q]=N.data[n++];break;}break;case 1:Q.data[++q]=N.data[n++];break;}}while(m<=M.tu)Q.data[++q]=M.data[m++];while(n<=N.tu)Q.data[++q]=N.data[n++];if(q>MAX_SIZE)return ERROR;Q.tu=q;return OK;}Status sub_matrix(TSMatrix M,TSMatrix N,TSMatrix &X){int i;if(M.mu!=N.mu || M.nu!=N.nu)return ERROR;for(i=1;i<=N.tu;++i)N.data[i].e*=-1;add_matrix(M,N,X);return OK;}//转置void transpose(TSMatrix M,TSMatrix &T){int p,col,q=1;T.mu = M.nu;T.nu = M.mu;T.tu = M.tu;if(T.tu){for(col=1;col<=M.nu;++col)for(p=1;p<=M.tu;++p)if(M.data[p].j==col){T.data[q].i=M.data[p].j;T.data[q].j=M.data[p].i;T.data[q++].e=M.data[p].e;}}}//快速转置Status fast_transpose(TSMatrix M,TSMatrix &T){int p,q;int col,t;T.mu = M.nu;T.nu = M.mu;T.tu = M.tu;int* num = (int*)malloc((M.nu+1)*sizeof(int));if(!num)return ERROR;int* cpot=(int*)malloc((M.nu+1)*sizeof(int));if(!cpot)return ERROR;if(T.tu){for(col=1;col<=M.nu;++col)num[col]=0;for(t=1;t<=M.tu;++t)++num[M.data[t].j];cpot[1]=1;for(col=2;col<=M.nu;++col)cpot[col]=cpot[col-1]+num[col-1];for(p=1;p<=M.tu;++p){col=M.data[p].j;q=cpot[col];T.data[q].i=M.data[p].j;T.data[q].j=M.data[p].i;T.data[q].e=M.data[p].e;++cpot[col];}}free(num);free(cpot);return OK;}void copy_matrix(TSMatrix M,TSMatrix &T){T=M;}void destroy_matrix(TSMatrix &M){M.mu=M.nu=M.tu = 0;}Status mult_matrix(TSMatrix M,TSMatrix N,TSMatrix &Q){int i,j,p,q;ElemType Qs;TSMatrix T;if(M.nu!=N.mu)return ERROR;Q.mu=M.mu;Q.nu=N.nu;Q.tu=0;transpose(N,T);for(i=1;i<=Q.mu;i++){q=1;for(j=1;j<=T.mu;j++){Qs=0;p=1;while(M.data[p].i<i)p++;while(T.data[q].i<j)q++;while(p<=M.tu && q<=T.tu&&M.data[p].i==i && T.data[q].i==j){switch(comp(M.data[p].j,T.data[q].j)){case -1:p++;break;case 0:Qs+=M.data[p++].e*T.data[q++].e;break;case 1:q++;break;}if(Qs){if(++Q.tu>MAX_SIZE)return ERROR;Q.data[Q.tu].i=i;Q.data[Q.tu].j=j;Q.data[Q.tu].e=Qs;}}}}return OK;}void print_matrix(TSMatrix M){int i,j,k=1;Triple *p=M.data+1;for(i=1;i<=M.mu;i++){for(j=1;j<=M.nu;j++){if(k<=M.tu && p->i==i &&p->j==j){printf("%3d",(p++)->e);k++;}else{printf("%3d",0);}}printf("\n");}}

这里,我们看看矩阵转置的操作。矩阵的转置是将矩阵中元素的行列位置进行互换。这里我们讨论稀疏矩阵的转置,对于一个矩阵A,如:

1  0  2  00  3  0  40  0  5  0其三元组的顺序表存储形式如下: i   j   e0     [0]1  1  1  [1]1  3  2  [2]2  2  3  [3]2  4  4  [4]3  3  5  [5]...      ...mu=3,nu=4,tu=5
这里需要注意的是,非零值按照一定的序列排序,转置过程需要保证非零元素的顺序,下面是矩阵转置的最简单的实现:
//将M转置transport(MAtrix M,MAtrix &X):begin:X.mu = M.nu;X.nu = M.mu;X.tu = M.tu;if 存在非零元素   for (i=1;i<M.nu;i++):     do      对于每个非零元素eif e的列号为当前矩阵的行号将e的转置为X中的非零元素end

这个算法由于每次都要遍历每个非零元素,算法复杂度为O(nu*tu)。

考虑,转置的关键问题在于,将i,j进行调换后将元素放置到data中合适的位置,如果我们能预先知道每一列(T中每一行)中的第一个非零元素在data中的位置,那么在将元素做转置操作时,便可直接放到data中的合适位置上去,为了求取每一列中第一个非零元素的位置,需要先求得每一列非零元素的个数。这里定义两个向量num和cpot,num[col]表示矩阵中第col列中非零元的数目,cpot[col]表示M中第col列的第一个非零元在data中的恰当位置。显然有

cpot[1]=1;

cpot[col]=cpot[col-1]+num[col-1]   2<=col<=M.nu

快速转置的算法实现如下:

fast_transpose(Matrix M,Matrix &X)begin:    X.mu=M.nu;    X.nu=M.mu;    X.tu=M.tu;   if 存在非零元素for i=1->M.nu初始化num向量for j=1->M.tu求取每列中非零元素个数cpot[1]=1;        for col=2->M.nu 求每列第一个非零元在data中的序号cpot向量        for p=1->M.tudo:取得非零元素的列号j;通过cpot 取得第j列的第一个非零元素在data中的序号qM.data[p].j ->X.data[q].iM.data[p].i->X.data[q].jM.data[p].e->X.data[q].e第j列的第一个非零元素在data中序号递增end




0 0