[数据结构]第五章-数组和广义表(读书笔记1)
2013-03-12 20:13
295 查看
第五章-数组和广义表
数组和广义表可以看成是线性表在下述含义上的扩展:表中的数据元素本身也是一个数据结构。
5.1 数组的定义
当n=1时,n维数组就退化为定长的线性表。反之,n维数组也可以看成是线性表的推广。数组一旦被定义,它的维数和维界就不再改变。
typedef ElemType Array2[m]
;
等价于
typedef ElemType Array1
;
typedef Array1 Array2[m];
5.2 数组的顺序表示和实现
对于数组,一旦规定了它的维数和各维的长度,便可为它分配存储空间。下面是顺序存储表示和实现。
5.3 矩阵的压缩存储
矩阵的压缩存储:为多个值相同的元只分配一个存储空间,对零元不分配空间。假若值相同的元素或者零元素在矩阵中的分布有一定规律,则我们称此类矩阵为特殊矩阵;反之称为稀疏矩阵。
5.3.1 特殊矩阵
对于对称矩阵,我们可以为每一对对称元分配一个存储空间,则可将n2个元压缩存储到n(n+1)/2个元的空间中。
所谓下(上)三角矩阵是指矩阵的上(下)三角(不包括对角线)中的元均为常数c或零的n阶矩阵。
对这类矩阵,我们也可按某个原则(或以行为主,或以对角线的顺序)将其压缩存储到一维数组上。
5.3.2 稀疏矩阵
其非零元较零元少,且分布没有一定规律,我们称之为稀疏矩阵。按照压缩存储的概念,只存储稀疏矩阵的非零元。因此除了存储非零元的值之外,还必须同时记下它所在行和列的位置(i,j)。
数组和广义表可以看成是线性表在下述含义上的扩展:表中的数据元素本身也是一个数据结构。
5.1 数组的定义
当n=1时,n维数组就退化为定长的线性表。反之,n维数组也可以看成是线性表的推广。数组一旦被定义,它的维数和维界就不再改变。
typedef ElemType Array2[m]
;
等价于
typedef ElemType Array1
;
typedef Array1 Array2[m];
5.2 数组的顺序表示和实现
对于数组,一旦规定了它的维数和各维的长度,便可为它分配存储空间。下面是顺序存储表示和实现。
/*标准头文件,提供宏va_start,va_arg和va_end*/ /*用于存取变长参数表*/ #include <stdarg.h> /*假设数组维数的最大值为8*/ #define MAX_ARRAY_DIM 8 typedef int ElemType; typedef struct{ /*数组元素基址,由InitArray分配*/ ElemType *base; /*数组维数*/ int dim; /*数组维界基址,由InitArray分配*/ int *bounds; /*数组映像函数常量基址,由InitArray分配*/ int *constants; }Array; Status InitArray(Array *A, int dim,...) {/*若维数dim和各维长度合法,则构造相应的数组A,并返回OK*/ int elemtotal; int 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){ exit(OVERFLOW); } /*若各维长度合法,则存入A.bounds,并求出A的元素总数elemtotal*/ elemtotal = 1; /*ap为va_list类型,是存放变长参数表信息的数组*/ 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){ exit(OVERFLOW); } /* 求映像函数的常数c,并存入A.constants[i-1],i=1,...dim */ A->constants = (int *)malloc(dim * sizeof(int)); if(!A->constants){ exit(OVERFLOW); } /*数组最后一维肯定是1,数组的增减以元素大小为单位*/ A->constants[dim - 1] = 1; for(i = dim - 2; i >= 0; --i){ A->constants[i] = A->bounds[i+1] * A->constants[i+1]; } return OK; } Status DestroyArray(Array *A) {/*销毁数组A*/ if(!A->base){ return ERROR; } free(A->base); A->base = NULL; if(!A->bounds){ return ERROR; } free(A->bounds); A->bounds = NULL; if(!A->constants){ return ERROR; } free(A->constants); A->constants = NULL; return OK; } Status Locate(Array A,va_list ap,int &off) {/*若ap指示的各下标值合法,则求出该元素在A中相对地址off*/ int i; int ind; off = 0; for (i = 0;i < A.dim; i++){ ind = va_arg(ap, int); if (ind < 0 || ind >= A.bounds[i]){ return OVERFLOW; } off += A.constants[i] * ind; } return OK; } Status Value(Array *A, ElemType *e,...) { Status result; int off; va_list ap; va_start(ap,e); if ((result = Locate(*A,ap,off)) <= 0){ return result; } *e = *(A->base + off); return OK; } Status Assign(Array *A, ElemType e,...) {/*A是n维数组,e为元素变量,随后是n个下标值*/ /*若下标不超界,则将e的值赋给所指定的A的元素,并返回OK*/ Status result; int off; va_list ap; va_start(ap,e); if ((result = Locate(*A,ap,off)) <= 0){ return result; } *(A->base + off) = e; return OK; } int _tmain(int argc, _TCHAR* argv[]) { Array A; int i,j,k,*p,dim = 3,bound1 = 3,bound2 = 4,bound3 = 2; /* a[3][4][2]数组 */ ElemType e,*p1; InitArray(&A,dim,bound1,bound2,bound3); /* 构造3*4*2的3维数组A */ p=A.bounds; printf("A.bounds="); for(i=0;i<dim;i++) /* 顺序输出A.bounds */ printf("%d ",*(p+i)); p=A.constants; printf("\nA.constants="); for(i=0;i<dim;i++) /* 顺序输出A.constants */ printf("%d ",*(p+i)); printf("\n%d页%d行%d列矩阵元素如下:\n",bound1,bound2,bound3); for(i=0;i<bound1;i++) { for(j=0;j<bound2;j++) { for(k=0;k<bound3;k++) { Assign(&A,i*100+j*10+k,i,j,k); /* 将i*100+j*10+k赋值给A[i][j][k] */ Value(&A,&e,i,j,k); /* 将A[i][j][k]的值赋给e */ printf("A[%d][%d][%d]=%2d ",i,j,k,e); /* 输出A[i][j][k] */ } printf("\n"); } printf("\n"); } p1=A.base; printf("A.base=\n"); for(i=0;i<bound1*bound2*bound3;i++) /* 顺序输出A.base */ { printf("%4d",*(p1+i)); if(i%(bound2*bound3)==bound2*bound3-1) printf("\n"); } DestroyArray(&A); return 0; }
5.3 矩阵的压缩存储
矩阵的压缩存储:为多个值相同的元只分配一个存储空间,对零元不分配空间。假若值相同的元素或者零元素在矩阵中的分布有一定规律,则我们称此类矩阵为特殊矩阵;反之称为稀疏矩阵。
5.3.1 特殊矩阵
对于对称矩阵,我们可以为每一对对称元分配一个存储空间,则可将n2个元压缩存储到n(n+1)/2个元的空间中。
所谓下(上)三角矩阵是指矩阵的上(下)三角(不包括对角线)中的元均为常数c或零的n阶矩阵。
对这类矩阵,我们也可按某个原则(或以行为主,或以对角线的顺序)将其压缩存储到一维数组上。
5.3.2 稀疏矩阵
其非零元较零元少,且分布没有一定规律,我们称之为稀疏矩阵。按照压缩存储的概念,只存储稀疏矩阵的非零元。因此除了存储非零元的值之外,还必须同时记下它所在行和列的位置(i,j)。
typedef int ElemType; #define MAXSIZE 100 /* 非零元个数的最大值 */ /* 三元组顺序表:稀疏矩阵的一种压缩存储算法 */ typedef struct { int i,j;/* 行下标,列下标 */ ElemType e;/* 非零元素值 */ }Triple; typedef struct { Triple data[MAXSIZE + 1]; /* 非零元三元组表,data[0]未用 */ int mu,nu,tu; /* 矩阵的行数、列数和非零元个数 */ }TSMatrix; Status CreateSMatrix(TSMatrix *M) { /* 创建稀疏矩阵M */ int i; int m,n,e; Status k; printf("请输入矩阵的行数,列数,非零元素数:"); scanf("%d,%d,%d",&(*M).mu,&(*M).nu,&(*M).tu); (*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", &m, &n, &e); k = 0; if(m < 1 || m > (*M).mu || n < 1 || n > (*M).nu){ /* 行或列超出范围 */ k = 1; } if(m <= (*M).data[i-1].i && n <= (*M).data[i-1].j){ /* 行或列的顺序有错 */ k = 1; } }while(k); (*M).data[i].i = m; (*M).data[i].j = n; (*M).data[i].e = e; } return OK; } void DestroySMatrix(TSMatrix *M) { /* 销毁稀疏矩阵M */ (*M).mu = 0; (*M).nu = 0; (*M).tu = 0; } void PrintSMatrix(TSMatrix M) { /* 输出稀疏矩阵M */ int i; printf("%d行%d列%d个非零元素。\n", M.mu, M.nu, M.tu); printf("行 列 元素值\n"); for(i = 1; i <= M.tu; i++){ printf("%2d%4d%8d\n", M.data[i].i, M.data[i].j, M.data[i].e); } } Status CopySMatrix(TSMatrix M,TSMatrix *T) { /* 由稀疏矩阵M复制得到T */ (*T) = M; return OK; } /* 1)将矩阵的行列值相互交换 2)将每个三元组中的i和j相互调换 3)重排三元组之间的次序便可实现矩阵的转置 */ Status TransposeSMatrix(TSMatrix M, TSMatrix *T) { /* 求稀疏矩阵M的转置矩阵T。算法5.1 */ int q; int col,p; (*T).mu = M.mu;/*矩阵的行*/ (*T).nu = M.nu;/*矩阵的列*/ (*T).tu = M.tu;/*非零元个数*/ /*算法的时间复杂度为O(nu*tu),即和M的列数及非零元的个数的乘积成正比*/ if ((*T).tu != 0){ q = 1; 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; ++q; } } } } return OK; } int comp(int c1,int c2) /* 另加 */ { /* AddSMatrix函数要用到 */ int i; if(c1 < c2){ i = 1; } else if(c1 == c2){ i = 0; } else{ i = -1; } return i; } Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix *Q) { /* 求稀疏矩阵的和Q=M+N */ Triple *Mp,*Me,*Np,*Ne,*Qh,*Qe; if(M.mu != N.mu || M.nu != N.nu){ return ERROR; } (*Q).mu = M.mu; (*Q).nu = M.nu; Mp = &M.data[1]; /* Mp的初值指向矩阵M的非零元素首地址 */ Np = &N.data[1]; /* Np的初值指向矩阵N的非零元素首地址 */ Me = &M.data[M.tu]; /* Me指向矩阵M的非零元素尾地址 */ Ne = &N.data[N.tu]; /* Ne指向矩阵N的非零元素尾地址 */ Qh = Qe = (*Q).data; /* Qh、Qe的初值指向矩阵Q的非零元素首地址的前一地址 */ while( Mp <= Me && Np <= Ne ){ Qe++; switch(comp(Mp->i, Np->i)){ case 1: *Qe = *Mp; Mp++; break; case 0: switch(comp(Mp->j,Np->j)){ /* M、N矩阵当前非零元素的行相等,继续比较列 */ case 1: *Qe = *Mp; Mp++; break; case 0: *Qe = *Mp; Qe->e += Np->e; if(!Qe->e){ /* 元素值为0,不存入压缩矩阵 */ Qe--; } Mp++; Np++; break; case -1: *Qe = *Np; Np++; break; }//switch break; case -1: *Qe = *Np; Np++; break; }//switch } if(Mp > Me){ /* 矩阵M的元素全部处理完毕 */ while(Np <= Ne){ Qe++; *Qe = *Np; Np++; } } if(Np > Ne){ /* 矩阵N的元素全部处理完毕 */ while(Mp <= Me){ Qe++; *Qe = *Mp; Mp++; } } (*Q).tu = Qe - Qh; /* 矩阵Q的非零元素个数 */ return OK; } Status SubtSMatrix(TSMatrix M, TSMatrix N, TSMatrix *Q) { /* 求稀疏矩阵的差Q=M-N */ int i; for(i = 1; i <= N.tu; i++){ N.data[i].e *= -1; } AddSMatrix(M,N,Q); return OK; } Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix *Q) { /* 求稀疏矩阵的乘积Q=M*N */ int i,j,h=M.mu,l=N.nu,Qn=0; /* h,l分别为矩阵Q的行、列值,Qn为矩阵Q的非零元素个数,初值为0 */ ElemType *Qe; if(M.nu != N.mu){ return ERROR; } (*Q).mu = M.mu; /*行数*/ (*Q).nu = N.nu; /*列数*/ Qe = (ElemType *)malloc(h * l * sizeof(ElemType)); /* Qe为矩阵Q的临时数组 */ /* 矩阵Q的第i行j列的元素值存于*(Qe+(i-1)*l+j-1)中,初值为0 */ for(i = 0; i < h * l; i++){ *(Qe + i) = 0; /* 赋初值0 */ } for(i = 1; i <= M.tu; i++){ /* 矩阵元素相乘,结果累加到Qe */ for(j = 1; j <= N.tu; j++){ if(M.data[i].j == N.data[j].i){ *(Qe + (M.data[i].i - 1) * l + N.data[j].j - 1) += M.data[i].e * N.data[j].e; } } } for(i = 1; i <= M.mu; i++){ for(j = 1;j <= N.nu; j++){ if(*(Qe+(i-1)*l+j-1)!=0){ Qn++; } (*Q).data[Qn].e = *(Qe + (i - 1) * l + j - 1); (*Q).data[Qn].i = i; (*Q).data[Qn].j = j; } } free(Qe); (*Q).tu = Qn; return OK; } int _tmain(int argc, _TCHAR* argv[]) { TSMatrix A,B,C; printf("创建矩阵A: "); CreateSMatrix(&A); PrintSMatrix(A); printf("由矩阵A复制矩阵B: "); CopySMatrix(A,&B); PrintSMatrix(B); DestroySMatrix(&B); printf("销毁矩阵B后:\n"); PrintSMatrix(B); printf("创建矩阵B2:(与矩阵A的行、列数相同,行、列分别为%d,%d)\n",A.mu,A.nu); CreateSMatrix(&B); PrintSMatrix(B); printf("矩阵C1(A+B): "); AddSMatrix(A,B,&C); PrintSMatrix(C); DestroySMatrix(&C); printf("矩阵C2(A-B): "); SubtSMatrix(A,B,&C); PrintSMatrix(C); DestroySMatrix(&C); printf("矩阵C3(A的转置): "); TransposeSMatrix(A,&C); PrintSMatrix(C); DestroySMatrix(&A); DestroySMatrix(&B); DestroySMatrix(&C); printf("创建矩阵A2: "); CreateSMatrix(&A); PrintSMatrix(A); printf("创建矩阵B3:(行数应与矩阵A2的列数相同=%d)\n",A.nu); CreateSMatrix(&B); PrintSMatrix(B); printf("矩阵C5(A*B): "); MultSMatrix(A,B,&C); PrintSMatrix(C); DestroySMatrix(&A); DestroySMatrix(&B); DestroySMatrix(&C); return 0; }
相关文章推荐
- 数据结构 第五章 数组和广义表
- [数据结构]第五章-数组和广义表(读书笔记2)
- 数据结构编程笔记十二:第五章 数组和广义表 数组顺序存储的实现
- [数据结构]第五章-数组和广义表(读书笔记3)
- 数据结构第五章--数组和广义表
- (数据结构第五章)数组实现
- 分别用数组和链表实现集合数据结构
- 《数据结构》第五章 树和二叉树 知识总结导图
- 第五章 数组(1):数组声明和初始化
- J2SE第五章——数组
- 算法练习:检测一个int(整型)数组中是否存在相同的数(只用基本数据结构)
- 数据结构 第四章 串、数组和广义表
- 5-6-广义表(扩展线性链表存储表示)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版
- 【数据结构】线性结构:栈&队列&数组
- 《coredump问题原理探究》Linux x86版5.4节C风格数据结构内存布局之数组coredump例子
- 《Delphi 算法与数据结构》学习与感悟[7]: 链表与数组的异同
- 微软等数据结构+算法面试100题(5)--怎样编写一个程序,把一个有序整数数组放到二叉树中
- 数据结构复习-数组、广义表、递归、哈夫曼数/并查集
- 第五章 数组与广义表
- 数据结构复习--数组的移动