数据结构实验报告-数组和广义表

合集下载

数据结构数组与广义表

数据结构数组与广义表

/*稀疏矩阵转置:经典算法,二维数组存储方式*/#include<stdio.h>#include<stdlib.h>#define m6#define n7typedef int ElementType;/*算法5.1稀疏矩阵转置经典算法*/void TransMatrix(ElementType source[m][n],ElementType dest[n][m]){ int i,j;for(i=0;i<m;i++)for(j=0;j<n;j++)dest[j][i]=source[i][j];}/*T(n)=O(m*n),形参的S(n)=O(m*n)*/int main(void){int i,j;/*二维数组存储稀疏矩阵,初始化source矩阵*/ElementType source[m][n]={{0,12,9,0,0,0,0},{0,0,0,0,0,0,0},{-3,0,0,0,0,14,0},{0,0,24,0,0,0,0},{0,18,0,0,0,0,0},{15,0,0,-7,0,0,0}},dest[n][m];TransMatrix(source,dest);printf("被转置的矩阵:\n");for(i=0;i<m;i++){for(j=0;j<n;j++)printf("%4d",source[i][j]);printf("\n");}printf("转置后的矩阵:\n");for(i=0;i<n;i++){for(j=0;j<m;j++)printf("%4d",dest[i][j]);printf("\n");}return0;}/*稀疏矩阵转置:行列互换转置算法,三元组表存储方式*/#include<stdio.h>#include<stdlib.h>typedef int ElementType;#define MAXSIZE1000/*三元组表结点类型定义*/typedef struct{int row,col;/*行号、列号*/ElementType e;/*元素值*/}Triple;/*三元组表类型的定义*/typedef struct{Triple data[MAXSIZE+1];/*顺序表*/int m,n,len;/*行数、列数、非零元素个数*/}TSMatrix;/*稀疏矩阵行列互换转置算法*/void TransposeMatrix(TSMatrix A,TSMatrix*B){int i,j,k,p;Triple temp;/*临时结点*//*新的行数、列数、非零元素个数确定*/B->m=A.n;B->n=A.m;B->len=A.len;/*存在非零结点*/if(B->len>0){/*行列互换*/for(i=1;i<=A.len;i++){B->data[i].row=A.data[i].col;B->data[i].col=A.data[i].row;B->data[i].e=A.data[i].e;}/*三元组表B按行号排序,注意同号的次序不能打乱,不能用一般的排序方法*/k=1;/*B中将要确定的结点下标*/for(i=1;i<=B->m;i++)/*遍历每个行号,行号从1--b->m*/for(j=k;j<=B->len;j++)/*B中k-1以前的已处理*/if(i==B->data[j].row){/*找到结点*/temp=B->data[j];/*把找到的结点暂存*/for(p=j;p>k;p--)/*向后移动元素,空出位置k*/B->data[p]=B->data[p-1];B->data[k++]=temp;/*确定第k个结点,准备下一结点下标*/ }}}/*行列交换T(n)=O(A.len)最坏移动元素的次数:A.len(A.len-1)/2*/int main(void){int i,j,k;/*定义三元组表A、B,并初始化A*/TSMatrix A={0,0,0,/*0下标不结点使用*/1,2,12,1,3,9,3,1,-3,3,6,14,4,3,24,5,2,18,6,1,15,6,4,-7},B;A.m=6;A.n=7;A.len=8;/*调用函数实现转置*/TransposeMatrix(A,&B);/*输出三元组形式*/printf("三元组表A:\n");for(i=1;i<=A.len;i++)printf("%4d%4d%4d\n",A.data[i].row,A.data[i].col,A.data[i].e);printf("三元组表B:\n");for(i=1;i<=B.len;i++)printf("%4d%4d%4d\n",B.data[i].row,B.data[i].col,B.data[i].e);/*输出矩阵形式*/printf("三元组表A表示的稀疏矩阵:\n");k=1;/*三元组表的结点下标*/for(i=1;i<=A.m;i++){for(j=1;j<=A.n;j++)if(A.data[k].row==i&&A.data[k].col==j){printf("%4d",A.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}printf("三元组表B表示的稀疏矩阵:\n");k=1;for(i=1;i<=B.m;i++){for(j=1;j<=B.n;j++)if(B.data[k].row==i&&B.data[k].col==j){printf("%4d",B.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}return0;}/*稀疏矩阵转置:列序递增转置算法,三元组表存储方式*/ #include<stdio.h>#include<stdlib.h>typedef int ElementType;#define MAXSIZE1000/*三元组表结点类型定义*/typedef struct{int row,col;/*行号、列号*/ElementType e;/*元素值*/}Triple;/*三元组表类型的定义*/typedef struct{Triple data[MAXSIZE+1];/*顺序表*/int m,n,len;/*行数、列数、非零元素个数*/}TSMatrix;/*算法5.2稀疏矩阵列序递增转置算法*/void TransposeMatrix(TSMatrix A,TSMatrix*B){/*i--A的结点下标,j--B的结点下标,k--A的列序号*/int i,j,k;/*新的行数、列数、非零元素个数确定*/B->m=A.n;B->n=A.m;B->len=A.len;/*存在非零结点*/if(B->len>0){j=1;/*B的结点下标j从1开始*/for(k=1;k<=A.n;k++)/*列序递增:1--A.n*/for(i=1;i<=A.len;i++)/*每个列号k,扫描三元组表A的所有元素*/ if(k==A.data[i].col){/*找到了*/B->data[j].row=A.data[i].col;B->data[j].col=A.data[i].row;B->data[j].e=A.data[i].e;j++;/*B的下一个结点下标*/}}}/*T(n)=O(A.n*A.len)*/int main(void){int i,j,k;/*定义三元组表A、B,并初始化A*/TSMatrix A={0,0,0,/*0下标不结点使用*/1,2,12,1,3,9,3,1,-3,3,6,14,4,3,24,5,2,18,6,1,15,6,4,-7},B;A.m=6;A.n=7;A.len=8;/*调用函数实现转置*/TransposeMatrix(A,&B);/*输出三元组形式*/printf("三元组表A:\n");for(i=1;i<=A.len;i++)printf("%4d%4d%4d\n",A.data[i].row,A.data[i].col,A.data[i].e);printf("三元组表B:\n");for(i=1;i<=B.len;i++)printf("%4d%4d%4d\n",B.data[i].row,B.data[i].col,B.data[i].e);/*输出矩阵形式*/printf("三元组表A表示的稀疏矩阵:\n");k=1;/*三元组表的结点下标*/for(i=1;i<=A.m;i++){for(j=1;j<=A.n;j++)if(A.data[k].row==i&&A.data[k].col==j){printf("%4d",A.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}printf("三元组表B表示的稀疏矩阵:\n");k=1;for(i=1;i<=B.m;i++){for(j=1;j<=B.n;j++)if(B.data[k].row==i&&B.data[k].col==j){printf("%4d",B.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}return0;}/*稀疏矩阵转置:一次定位快速转置算法,三元组表存储方式*/ #include<stdio.h>#include<stdlib.h>typedef int ElementType;#define MAXSIZE1000/*三元组定义*/typedef struct{int row,col;/*行号、列号*/ElementType e;/*元素值*/}Triple;/*三元组表定义*/typedef struct{Triple data[MAXSIZE+1];/*顺序表*/int m,n,len;/*行数、列数、非零元素个数*/}TSMatrix;/*算法5.3稀疏矩阵一次定位快速转置算法*/void FastTransposeMatrix(TSMatrix A,TSMatrix*B){/*col--A的列号、B的行号,p--A的结点下标,q--B的结点下标*/int col,p,q;/*定义数组num[A.n+1],用于分别存储每列的非零元素个数*/int*num=(int*)malloc(sizeof(int)*(A.n+1));/*定义数组position[A.n+1],第col列第一个非零元素在B中的位置下标*/ int*position=(int*)malloc(sizeof(int)*(A.n+1));/*新的行数、列数、非零元素个数确定*/B->m=A.n;B->n=A.m;B->len=A.len;/*存在非零结点*/if(B->len>0){/*每列非零元素个数初始化为0*/for(col=1;col<=A.n;col++)num[col]=0;/*统计每列中非零元素的个数*/for(p=1;p<=A.len;p++)num[A.data[p].col]++;/*设置position[1]的值为1,第1列第一个非零元素在B的位置为1*/position[1]=1;/*确定第col列第一个非零元素在B的位置*/for(col=2;col<=A.n;col++)position[col]=position[col-1]+num[col-1];/*将被转置矩阵的三元组表A从头至尾扫描一次,实现矩阵转置*/for(p=1;p<=A.len;p++){col=A.data[p].col;/*所在列号*/q=position[col];/*在B存放的位置*/B->data[q].row=A.data[p].col;/*交换*/B->data[q].col=A.data[p].row;B->data[q].e=A.data[p].e;position[col]++;/*col列的下一个非零元素在B的位置*/ }}}/*f(n)=A.n+A.len+1+(A.n-1)+A.len=2(A.n+A.len),即T(n)=O(A.n+A.len)*/ /*S(n)=A.n+1+A.n+1=2(A.n+1),即S(n)=O(A.n)*/int main(void){int i,j,k;/*定义三元组表A、B,并初始化A*/TSMatrix A={0,0,0,/*0下标不结点使用*/1,2,12,1,3,9,3,1,-3,3,6,14,4,3,24,5,2,18,6,1,15,6,4,-7},B;A.m=6;A.n=7;A.len=8;/*调用函数实现转置*/FastTransposeMatrix(A,&B);/*输出三元组形式*/printf("三元组表A:\n");for(i=1;i<=A.len;i++)printf("%4d%4d%4d\n",A.data[i].row,A.data[i].col,A.data[i].e);printf("三元组表B:\n");for(i=1;i<=B.len;i++)printf("%4d%4d%4d\n",B.data[i].row,B.data[i].col,B.data[i].e);/*输出矩阵形式*/printf("三元组表A表示的稀疏矩阵:\n");k=1;/*三元组表的结点下标*/for(i=1;i<=A.m;i++){for(j=1;j<=A.n;j++)if(A.data[k].row==i&&A.data[k].col==j){printf("%4d",A.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}printf("三元组表B表示的稀疏矩阵:\n");k=1;for(i=1;i<=B.m;i++){for(j=1;j<=B.n;j++)if(B.data[k].row==i&&B.data[k].col==j){printf("%4d",B.data[k].e);k++;}elseprintf("%4d",0);printf("\n");}return0;}/*稀疏矩阵转置:一次定位快速转置算法,三元组表存储方式*/#include<stdio.h>#include<stdlib.h>typedef int ElementType;/*十字链表的类型定义*//*非零元素结点的定义*/typedef struct OLNode{int row,col;/*非零元素:行号、列号、值*/ElementType value;struct OLNode*right;/*行后继链域、列后继链域*/struct OLNode*down;}OLNode,*OLink;/*OLNode结点类型、OLink指向结点的指针类型*//*十字链表的定义*/typedef struct{OLink*row_head;/*行头指针向量,二重指针,指向第0个行链指针*/ OLink*col_head;/*列头指针向量,二重指针,指向第0个列链指针*/ int m,n,len;/*稀疏矩阵的行数、列数、非零元素的个数*/}CrossList;/*十字链表类型*//*算法5.4创建十字链表*/void CreateCrossList(CrossList*M){int m,n,t;/*接收行数、列数、个数*/OLNode*p,*q;/*p指向新结点*/int i,j,e;/*接收结点的行号、列号、值*//*确定十字链表的成员m、n、len的值*/printf("输入M的行数、列数、非零元素的个数:\n");scanf("%d%d%d",&m,&n,&t);/*输入M的行数,列数和非零元素的个数*/ M->m=m;M->n=n;M->len=t;/*申请行列链指针分量,并确定row_head、col_head的值*//*申请m+1个行链指针分量,m+1个行链表*/if(!(M->row_head=(OLink*)malloc((m+1)*sizeof(OLink))))printf("error");/*申请n+1个列链指针分量,n+1个列链表*/if(!(M->col_head=(OLink*)malloc((n+1)*sizeof(OLink))))printf("error");/*把所有行列链指针置空*/for(i=1;i<=m;i++){M->row_head[i]=NULL;}for(i=1;i<=n;i++){M->col_head[i]=NULL;}/*链入结点*/printf("请输入非零结点行号、列号、值:(行号为0则结束输入)\n");for(scanf("%d%d%d",&i,&j,&e);i!=0;scanf("%d%d%d",&i,&j,&e)){ /*生成新结点*/if(!(p=(OLNode*)malloc(sizeof(OLNode))))printf("error");p->row=i;p->col=j;p->value=e;/*链入i行*/if(M->row_head[i]==NULL){/*是行中的第1个结点*/p->right=M->row_head[i];/*新结点尾置空*/M->row_head[i]=p;/*链接新结点*/}else{/*把q定位在第i行的未结点,利用空循环*/for(q=M->row_head[i];q->right&&q->right->col<j;q=q->right);p->right=q->right;/*新结点尾置空*/q->right=p;/*链接新结点*/}/*链入j列*/if(M->col_head[j]==NULL){/*是列中的第1个结点*/p->down=M->col_head[j];/*新结点尾置空*/M->col_head[j]=p;/*链接新结点*/}else{/*把q定位在第j行的未结点,利用空循环*/for(q=M->col_head[j];q->down&&q->down->row<i;q=q->down);p->down=q->down;/*新结点尾置空*/q->down=p;/*链接新结点*/}}}/*输出十字链表1*/void PrintCrossList(CrossList*M){int i,j;OLNode*p;for(i=1;i<=M->m;i++){/*以行为主输出*/p=M->row_head[i];/*行链起点*/for(j=1;j<=M->n;j++){if(p&&p->col==j){/*p存在且位于j列*/printf("%4d",p->value);p=p->right;/*链表下滑,不回溯*/}elseprintf("%4d",0);}printf("\n");}}/*输出十字链表2*/void out_Matrix(CrossList*M){int i,j;OLNode*p;for(i=1;i<=M->m;i++){/*以行为主输出*/for(j=1;j<=M->n;j++){p=M->row_head[i];/*每次均从本行头指针开始,p回溯*/while(p!=NULL){if(p->col==j)break;/*找到结点*/p=p->right;}if(p!=NULL)/*输出结点*/printf("%4d",p->value);elseprintf("%4d",0);}printf("\n");/*换行*/}}int main(void){CrossList M;CreateCrossList(&M);PrintCrossList(&M);out_Matrix(&M);return0;}/*广义表的头尾链表:头尾即表头、表尾的意思*/#include<stdio.h>#include<stdlib.h>#define AutoType int/*原子结点类型*//*结点分类:用枚举类型实现*/typedef enum{ATOM,LIST/*枚举值:值ATOM表示原子结点,值LIST表示子表*/ }ElemTag;/*ElemTag类型的变量仅有两个可取的枚举值*//*广义表结点类型的定义,广义表类型的定义*/typedef struct GLNOde{ElemTag tag;/*标志位tag用来区分原子结点和表结点*//*通过共用体实现广义表结点:要么是原子结点、要么是表结点*/ union{AutoType atom;struct{struct GLNode*hp,*tp;}htp;}atom_htp;}GLNode,*GList;int main(void){return0;}/*二维数组是“数据元素为一维数组”的线性表*//*即元素的类型是一种数据结构*/#include<stdio.h>#include<stdlib.h>#define M3#define N4#define ElementType int/*一维数组类型定义*/typedef struct{ElementType data[N];/*N个数据元素为ElementType的顺序表*/ }Array;/*新的数据类型为Array*/int main(void){Array A[M];/*M个数据类型为Array的顺序表*/int i,j;/*随机输入矩阵的值*/for(i=0;i<M;i++)for(j=0;j<N;j++)A[i].data[j]=rand()%100;/*范围0--99*//*输出矩阵的值*/for(i=0;i<M;i++){for(j=0;j<N;j++)printf("%4d",A[i].data[j]);printf("\n");}return0;}/*一维数组的顺序存储*/#include<stdio.h>#include<stdlib.h>int main(void){int a[10];/*顺序存储*/printf("a[0]的地址:%d\n",&a[0]);printf("a[5]的地址(内部实现):%d\n",&a[5]);/*Loc(a[i])=Loc(a[0])+(i-0)*size*//*Loc(a[i])=Loc(a[0])+(i)*size*//*size自动分配,例如+5,地址实质上增大了20*/printf("a[5]的地址(公式计算):%d\n",&a[0]+5);return0;}/*二维数组的顺序存储*/#include<stdio.h>#include<stdlib.h>int main(void){int a[5][4];/*以行为主的顺序存储,m=5行n=4列*/printf("a[0][0]的地址:%d\n",&a[0][0]);printf("a[3][2]的地址(内部实现):%d\n",&a[3][2]);/*Loc(a[i][j])=Loc(a[0][0])+((i-0)*n+(j-0))*size*//*Loc(a[i][j])=Loc(a[0][0])+(i*n+j)*size*/printf("a[3][2]的地址(公式计算):%d\n",&a[0][0]+3*4+2);return0;}/*三维数组的顺序存储*/#include<stdio.h>#include<stdlib.h>int main(void){int a[5][4][6];/*以行为主的顺序存储,m=5行n=4列r=6纵*/printf("a[0][0][0]的地址:%d\n",&a[0][0][0]);printf("a[3][2][4]的地址(内部实现):%d\n",&a[3][2][4]);/*Loc(a[i][j][k])=Loc(a[0][0][0])+((i-0)*n*r+(j-0)*r+(k-1))*size*//*Loc(a[i][j][k])=Loc(a[0][0][0])+(i*n*r+j*r+k)*size*/printf("a[3][2][4]]的地址(公式计算):%d\n",&a[0][0][0]+3*4*6+2*6+4);return0;}/*三角矩阵的压缩存储*/#include<stdio.h>#include<stdlib.h>#define ElementType int#define MAXSIZE1000/*矩阵的压缩类型定义*/typedef struct{ElementType data[MAXSIZE+1];/*非0元素的空间,data[0]未用*/int n,len;/*n为矩阵的阶数,即n*n矩阵;len非0元素的个数*/ }Matrix;int main(void){int i,j;/*下三角矩阵变量A的定义及初始化*/Matrix A={0,/*未用*/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};A.n=5;/*阶数n*/A.len=A.n*(A.n+1)/2;/*输出下三角矩阵*/for(i=1;i<=A.n;i++){for(j=1;j<=A.n;j++)if(i<j)printf("%4d",0);else/*下标从1考虑,第几个元素的下标就是几*/printf("%4d",A.data[i*(i-1)/2+j]);printf("\n");}return0;}/*三对角带状矩阵的压缩存储*/#include<stdio.h>#include<stdlib.h>#define ElementType int#define MAXSIZE1000/*矩阵的压缩类型定义*/typedef struct{ElementType data[MAXSIZE+1];/*非0元素的空间,data[0]未用*/int n,len;/*n为矩阵的阶数,即n*n矩阵;len非0元素的个数*/ }Matrix;int main(void){int i,j;/*三对角带状矩阵变量A的定义及初始化*/Matrix A={0,/*未用*/1,2,2,3,4,3,4,5,4,5,6,5,6};A.n=5;/*阶数n*/A.len=3*A.n-2;/*输出三对角带状矩阵*/for(i=1;i<=A.n;i++){for(j=1;j<=A.n;j++)if(j==i-1||j==i||j==i+1)/*三对角带状条件*/printf("%4d",A.data[2*(i-1)+j]);elseprintf("%4d",0);printf("\n");}return0;}。

数据结构-第五章 数组与广义表-文档资料

数据结构-第五章 数组与广义表-文档资料

上 三 角 矩 阵 下 三 角 矩 阵
a00 a10 a 20 an10
0 1 2
a01 a11 a21 an11
3 4
a02 a12 a22 an12
5

6 7
a0 n1 a1n1 a2 n1 an1n1
行 列 值 (row) (col) (value) 0 4 91 1 1 11 2 5 28 3 0 22 3 2 -6 5 1 17 5 3 39 6 0 16
用三元组表表示的稀疏矩阵及其转置
行 列 值 (row) (col) (value) 0 3 22 0 6 15 1 1 11 1 5 17 2 3 -6 3 5 39 4 0 91 5 2 28 行 列 值 (row) (col) (value) 0 4 91 1 1 11 2 5 28 3 0 22 3 2 -6 5 1 17 5 3 39 6 0 16
4 5 6 7 8 9 10
B a00 a01 a10 a11 a12 a21 a22 a23 … an-1n-2 an-1n-1
三对角矩阵中除主对角线及在主对角线上 下最临 近的两条对角线上的元素外,所有其它元素均为 0。总共有3n-2个非零元素。 将三对角矩阵A中三条对角线上的元素按行存放在 一维数组 B 中,且a00存放于B[0]。 在三条对角线上的元素aij 满足 0 i n-1, i-1 j i+1 在一维数组 B 中 A[i][j] 在第 i 行,它前面有 3*i-1 个非零元素, 在本行中第 j 列前面有 j-i+1 个,所 以元素 A[i][j] 在 B 中位置为 k = 2*i + j。
三对角矩阵的压缩存储

数据结构:第5章 数组与广义表1-数组

数据结构:第5章 数组与广义表1-数组

中的元素均为常数。下三角矩阵正好相反,它的主对
数据结构讲义
第5章 数组与广义表
—数组
数组和广义表
数组和广义表可看成是一种特殊的 线性表,其特殊在于,表中的数据 元素本身也是一种线性表。
几乎所有的程序设计语言都有数组 类型。本节重点讲解稀疏矩阵的实 现。
5.1 数组的定义
由于数组中各元素具有统一的类型,并且 数组元素的下标一般具有固定的上界和下 界,因此,数组的处理比其它复杂的结构 更为简单。
nm
aa1221
aa2222
…………....
aam2n2 ………………..
aamm11 aamm22 ………….... aammnn LLoocc(a( iaj)ij=)L=Loco(ca(a111)1+)[+([j(-i1-)1m)n++((i-j1-1)])*]*l l
aa1mn 1 aa2mn2 …………....
其存储形式如图所示:
15137 50800 18926 30251
a00 a10 a 11 a20 a21 a23 ………………..
70613
an-1 0 a n-1 1 a n-1 2 …a n-1 n-1
图 5.1 对称矩阵
在这个下三角矩阵中,第i行恰有i+1个元素,元素总
数为:
n(n+1)/2
5.2 数组的顺序表示和实现
由于计算机的内存结构是一维的,因此用 一维内存来表示多维数组,就必须按某种 次序将数组元素排成一列序列,然后将这 个线性序列存放在存储器中。
又由于对数组一般不做插入和删除操作, 也就是说,数组一旦建立,结构中的元素 个数和元素间的关系就不再发生变化。因 此,一般都是采用顺序存储的方法来表示 数组。

数组与广义表的算法的实验报告

数组与广义表的算法的实验报告

数组与广义表的算法实验工具:visual C++实验内容:1、三元组表示稀疏矩阵的转置算法(一般&快速)<1-7页> 2、稀疏矩阵乘法、加法的算法(一般&十字链表)<8-21页> 3、广义表的各种算法<22-28页> 体验:通过利用visual C++实验工具,实现数组与广义表各类算法的过程中,本人对数组与广义表的知识有了更深的了解,而且认识到数组与广义表各类操作可由形式多样的算法结构实现。

算法并非统一标准的,同样的结果可有多种算法得出,算法的编写鼓励创造性思维。

1、三元组表示稀疏矩阵的转置算法(一般&快速)代码:#include<stdio.h>#include<conio.h>#include<stdlib.h>#include<windows.h>#define OK 1#define ERROR 0#define OVERFLOW 0#define MAXSIZE 100#define MAXRC 100typedef int ElemType;typedef struct{int i,j;ElemType e;}Triple;typedef struct{Triple data[MAXSIZE+1]; //非零元三元组int rpos[MAXRC+1]; //各行第一个非零元的位置表int mu,nu,tu; //矩阵的行数、列数和非零元个数}RLSMatrix;CreateSMatrix(RLSMatrix &M) //创建稀疏矩阵M{int i,m,n;ElemType e;int k,j;printf("输入矩阵的行数、列数、非零元的个数:");scanf("%d%d%d",&M.mu,&M.nu,&M.tu);M.data[0].i=0;for(i=1;i<=M.tu;i++){j=0;do{j++;if(j>3) //控制跳出死循环{printf("本次输入失败!");return ERROR;}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||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;} //end forprintf("\n");return(OK);}void DestroySMatrix(RLSMatrix &M) //销毁稀疏矩阵M{M.mu=0;M.nu=0;M.tu=0;}void PrinRLSMatrix(RLSMatrix M) //遍历稀疏矩阵M{int i;printf("稀疏矩阵对应的三元组表为:\n\n");printf("行列元素值、\n\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);printf("\n\n");}void print(RLSMatrix A) //打印矩阵函数,以通常形式输出矩阵{int k=1,a,b;printf("稀疏矩阵的通常形式为:\n");int M[MAXSIZE][MAXSIZE];for(a=0;a<A.mu;a++) //初始化矩阵M{for(b=0;b<A.nu;b++)M[a][b]=0;}while(k<=A.tu){M[A.data[k].i-1][A.data[k].j-1]=A.data[k].e;k++;}for(a=0;a<A.mu;a++){printf(" | ");for(b=0;b<A.nu;b++)printf("%d ",M[a][b]);printf(" | \n");}}void showtip() //菜单{printf(" ********************请选择要执行的操作********************\n\n");printf(" & 1 采用一般算法实现&\n");printf(" & 2 采用快速转置的算法实现&\n");printf(" & 3 同时采用两种算法,先显示一般算法,再显示快速算法&\n");printf(" **********************************************************\n\n");}////头文件结束TransposeSMatrix(RLSMatrix M,RLSMatrix &T) //求稀疏矩阵M的转置矩阵T(一般算法) {int p,q,col;T.mu=M.nu;T.nu=M.mu;T.tu=M.tu;if(T.tu){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;}FastTransposeSMatrix(RLSMatrix M,RLSMatrix &T) //快速转置算法{int p,q,t,col,*num,*cpot;num=(int*)malloc((M.nu+1)*sizeof(int));cpot=(int*)malloc((M.nu+1)*sizeof(int));T.mu=M.nu;T.nu=M.mu;T.tu=M.tu;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];printf("\n辅助数组的值为:\n");printf("列号:");for(t=1;t<=M.nu;++t)printf("%4d",t);printf("\n");printf("num[]");for(t=1;t<=M.nu;++t)printf("%4d",num[t]);printf("\n");printf("cpot[]");for(t=1;t<=M.nu;++t)printf("%4d",cpot[t]);printf("\n\n");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 main(){int result;int j;RLSMatrix A,B;//************************************************COORD Co={0,0};DWORD Write;SetConsoleTitle("稀疏矩阵的转置\n");HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hOut,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND _INTENSITY);FillConsoleOutputAttribute(hOut,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROU ND_INTENSITY,100000000,Co,&Write);///windows的API函数,用来设置控制台标题do{showtip(); //调用菜单函数int i;scanf("%d",&i);switch(i){case 1:printf("创建矩阵A:");if((result=CreateSMatrix(A))==0)exit(ERROR);PrinRLSMatrix(A);printf("求A的转置矩阵B(一般算法):\n");TransposeSMatrix(A,B);PrinRLSMatrix(B);print(B);DestroySMatrix(B);printf("\n\n");break;case 2:printf("创建矩阵A:");if((result=CreateSMatrix(A))==0)exit(ERROR);PrinRLSMatrix(A);printf("求A的转置矩阵B(快速转置):\n");FastTransposeSMatrix(A,B);PrinRLSMatrix(B);print(B);DestroySMatrix(A);DestroySMatrix(B);printf("\n\n");break;case 3:printf("创建矩阵A:");if((result=CreateSMatrix(A))==0)exit(ERROR);PrinRLSMatrix(A);printf("求A的转置矩阵B------(一般算法):\n");TransposeSMatrix(A,B);PrinRLSMatrix(B);print(B);DestroySMatrix(B);printf("\n\n");printf("求A的转置矩阵B------(快速转置):\n");FastTransposeSMatrix(A,B);PrinRLSMatrix(B);print(B);DestroySMatrix(A);DestroySMatrix(B);printf("\n\n");break;}printf(" **********请选择是否继续输入其他稀疏矩阵?**********\n");printf(" 1 是,输入其他矩阵\n");printf(" 0 否,不输入\n");printf(" ****************************************************");fflush(stdin);//清除输入缓存区scanf("%d",&j);}while(j==1);}运行结果:(1)创建矩阵(2)一般转置(3)快速转置2、稀疏矩阵乘法、加法的算法(一般&十字链表)代码:#include<stdio.h>#include<malloc.h>#define Size 2501# define Size1 51typedef struct{int i;int j;int e;//非零元的值}triple; //定义三元组typedef struct{triple data[Size+1];//矩阵中的元素int rops[Size1+1];// rops[i]为第i行元素中的首非零元在data[]中的序号int mu;//行数int nu;//列数int tu;//非零元数} juzhen;//定义矩阵typedef struct node// 定义十字链表元素{int i,j,e;struct node *right,*down;// 该非零元所在行表和列表的后继元素}node,*link;typedef struct // 定义十字链表对象结构体{link *rhead,*chead;//行和列的头指针int m,n,t;// 系数矩阵的行数,列数,和非零元素个数}crosslist;void createcross(crosslist &M)//建立十字链表{int i,j,e,k;node *p,*q;printf("输入行,列和非零元数,空格隔开:\n");scanf("%d %d %d",&M.m,&M.n,&M.t);M.rhead=(link *)malloc((M.m+1)*sizeof(link));//给行和列的头指针分配内存M.chead=(link *)malloc((M.n+1)*sizeof(link));for(k=1;k<=M.m;k++)//初始化行,列的头指针M.rhead[k]=NULL;for(k=1;k<=M.n;k++)M.chead[k]=NULL;printf("输入非零元的行,列和值,空格隔开:\n");for(k=1;k<=M.t;k++)//输入非零元{scanf("%d %d %d",&i,&j,&e);p=(node *)malloc(sizeof(node));p->i=i;p->j=j;p->e=e;if(M.rhead[i]==NULL||M.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标{p->right=M.rhead[i];M.rhead[i]=p;}else{for(q=M.rhead[i];(q->right)&&q->right->j<j;q=q->right);//空循环找到第一个列标大于或等于插入元素列标的元素p->right=q->right;q->right=p;}if(M.chead[j]==NULL||(M.chead[j]->i>i))//插入元素所在列无非零元或首非零元的行标大于插入元素的行标{p->down=M.chead[j];M.chead[j]=p;}else{for(q=M.chead[j];(q->down)&&q->down->i<i;q=q->down);//空循环找到第一个行标大于或等于插入元素行标的元素p->down=q->down;q->down=p;}}}void printcross(crosslist A)//输出十字链表{if(A.m==0)printf("十字链表为空!\n");else{printf("十字链表为:\n");int i,j;for(i=1;i<=A.m;i++){link p=A.rhead[i];for(j=1;j<=A.n;j++){if((p)&&(j==p->j)){printf("%5d",p->e);p=p->right; }elseprintf("%5d",0);}printf("\n");}}printf("\n");}crosslist addcross(){printf("十字链表加法:\n");crosslist a,b;// 创建两个十字链表对象,并初始化createcross(a);createcross(b);node *pre,*h[51],*pa,*pb,*q;//定义辅助指针,pa,pb分别为a,b当前比较的元素,pre为pa的前驱元素int i,j,k=0,m,n; //h[j]指向j列的当前插入位置if(a.m!=b.m||a.n!=b.n)printf("格式不对,不能相加!\n");else{for(i=1;i<=a.m;i++){pa=a.rhead[i];pb=b.rhead[i];pre=NULL;for(j=1;j<=a.n;j++)h[j]=NULL;while(pb){link p;p=(node *)malloc(sizeof(node)); // 开辟新节点,存储b中取出的元素p->i=pb->i;p->j=pb->j;p->e=pb->e;if(pa==NULL||pa->j>pb->j)//当a此行已经检查完或者pb因该放在pa前面{if (pre==NULL)a. rhead[p->i]=p;elsepre->right=p;p->right=pa;pre=p;if (h[p->j]==NULL)//当前插入位置下面无非零元//因为是逐行处理,so,h[p->j],依次下移//因此每次都是指向插入的位置{a. chead [p->j]= p;p->down = NULL;}else{p->down = h[p->j]->down;h[p->j]->down = p;}h[p->j]=p;//*******h[p->j]下移指向下次插入的位置pb=pb->right;//pb指向该行下个元素}else if((pa&&pa->j<pb->j))//只要移动pa的指针****先不加||(pb==NULL&&pa){pre = pa;h[pa->j]=pa;//移动h[],使其指向下次插入的位置pa = pa->right;}else if(pa->j==pb->j){pa->e+=pb->e;if(pa->e)//不为零{pre=pa;h[pa->j]=pa;pb=pb->right;//加}else//pa->e为零,删除节点{if (pre ==NULL)a.rhead [pa->i]=pa->right;else{pre->right=pa->right;}p=pa;//p指向pa,用来在下面修改列指针pa=pa->right;if (h [p->j]==NULL)a.chead [p->j]=p->down;else{h[p->j]->down=p->down;}free(p);pb=pb->right;}}}}}return a;}void multycross(crosslist &c)//十字链表乘法{node *p,*q,*u,*v,*p1,*p2;crosslist a,b;link *r;int i,j,k,e;printf("十字链表乘法:\n");createcross(a);createcross(b);if(a.n!=b.m)printf("格式错误,不能相乘!\n");else{c.m=a.m;c.n=b.n;c.t=0;c.rhead=(link *)malloc((a.m+1)*sizeof(link));//给行和列的头指针分配内存c.chead=(link *)malloc((b.n+1)*sizeof(link));for(k=1;k<=a.m;k++)//初始化行,列的头指针c.rhead[k]=NULL;for(k=1;k<=b.n;k++)c.chead[k]=NULL;r=(link *)malloc((b.n+1)*sizeof(link));for(i=1;i<=a.m;i++){u=(node *)malloc(sizeof(node));u->e=0;u->i=0;u->j=0;for(k=1;k<=b.n;k++)//初始化r[]r[k]=u;p1=p=a.rhead[i];for(j=1;j<=b.n;j++){p=p1;q=b.chead[j];v=(node *)malloc(sizeof(node));//初始化v,v为将插入c矩阵的元素v->e=0;v->i=i;v->j=j;while(p&&q){if(p->j>q->i)q=q->down;else if(p->j<q->i)p=p->right;else{v->e+=p->e*q->e;p=p->right;q=q->down;}}if(v->e)//如果不为零,则插入c矩阵中{//同建立十字链表if(c.rhead[i]==NULL||c.rhead[i]->j>j)//插入元素所在行无非零元或首非零元的列标大于插入元素的列标{v->right=c.rhead[i];c.rhead[i]=v;}else{for(p2=c.rhead[i];(p2->right)&&(p2->right->j<j);p2=p2->right);//空循环找到第一个列标大于或等于插入元素列标的元素v->right=p2->right;p2->right=v;}if(c.chead[j]==NULL||c.chead[j]->i>i)//插入元素所在列无非零元或首非零元的行标大于插入元素的行标{v->down=c.chead[j];c.chead[j]=v;}else{for(p2=c.chead[j];(p2->down)&&(p2->down->i<i);p2=p2->down);//空循环找到第一个行标大于或等于插入元素行标的元素v->down=p2->down;p2->down=v;}}}}}}void create(juzhen & M) //创建稀疏矩阵{int i,t=0;printf("输入矩阵行数和列数and非零元的个数,以空格隔开:\n");scanf("%d %d %d",&M.mu,&M.nu,&M.tu);printf("输入矩阵非零元的行,列,和数值(中间空格隔开):\n");for(i=1;i<=M.tu;i++)scanf("%d %d %d",&M.data[i].i,&M.data[i].j,&M.data[i].e); //输入三元组的元素 for(i=1;i<=Size1;i++)//初始化rops【】M.rops[i]=0;for(i=1,t=1;i<=M.mu;i++)//得到各行第一个元素的序号{M.rops[i]=t;while(M.data[t].i<=i&&t<=M.tu)//遇到i行非零元,则t累加t++;}}void add(juzhen A,juzhen B,juzhen & C)//稀疏矩阵加法{int k=1,temp=0,k1=1, k2=1;//k1,k2,k分别控制A,B,C中非零元的序号变化printf("稀疏矩阵加法:\n");create(A);create(B);if(A.mu!=B.mu||A.nu!=B.nu)printf("格式不对,不能相加!\n");else{while(k1<=A.tu&&k2<=B.tu)//当A,B中的非零元都没用完{if(A.data[k1].i<B.data[k2].i)//A当前k1指向的元素的行标小于列标直接把data【k1】的值赋给c中data【k】C.data[k++]=A.data[k1++];else if(A.data[k1].i>B.data[k2].i)//同上C.data[k++]=B.data[k2++];else//data[k1],data[k2]行标相同{if(A.data[k1].j>B.data[k2].j)//data[k1]列标大于data[k2]列标,则把data[k2]的值赋给data[k]C.data[k++]=B.data[k2++];else if(A.data[k1].j<B.data[k2].j)//同上C.data[k++]=A.data[k1++];else //行,列标都相同{temp=0;temp=A.data[k1].e+B.data[k2].e;if(temp)//相加后不为零{C.data[k].i=A.data[k1].i;C.data[k].j=A.data[k1].j;C.data[k].e=temp;k++;}k1++;k2++;}}}while(k1<=A.tu)//B中非零元已用完,A中还有非零元C.data[k++]=A.data[k1++];while(k2<=B.tu)//A中非零元已用完,B中还有非零元C.data[k++]=B.data[k2++];C.mu=A.mu;//确定C的行列数和非零元个数C.nu=A.nu;C.tu=k-1;}}void print(juzhen A)//输出稀疏矩阵{printf("\n矩阵为:\n");int i,j,k=1;if(A.mu==0)printf("矩阵为空!\n");else if(A.tu==0)//矩阵元素为空printf("零矩阵!\n");elsefor(i=1;i<=A.mu;i++)//逐行输出{for(j=1;j<=A.nu;j++){if(A.data[k].i==i&&A.data[k].j==j)//行和列分别对应相等则输出相应非零元,否则输出零printf("%5d",A.data[k++].e);elseprintf("%5d",0);}printf("\n");//该行输出结束,空行输出下一行}printf("\n");}void multy(juzhen A,juzhen B,juzhen &C)//稀疏矩阵乘法{int arow,brow,ccol,temp[51],p,q,t,tp,i;//各变量代表含义见下面printf("稀疏矩阵乘法:\n");create(A);create(B);if(A.nu!=B.mu)printf("格式错误,不能相乘!\n");else{C.mu=A.mu;//初始化c的行列及非零元个数C.nu=B.nu;C.tu=0;if(A.nu!=B.mu)printf("A,B格式不对不能相乘!\n");else //{for(arow=1;arow<=A.mu;arow++)//arow为当前A矩阵的行标{for(i=0;i<51;i++)//初始化temptemp[i]=0;if(arow<A.mu)tp=A.rops[arow+1];//tp为arow+1行的首非零元在data【】中的序号else //arow为最后一行tp=A.tu+1;for(p=A.rops[arow];p<tp;p++)//p为A中当前元素在data[]中的序号{brow=A.data[p].j;//brow为与B矩阵中的相应行对应的A中当前元素的列标if(brow<B.mu)t=B.rops[brow+1];//t为brow+1行的首非零元在B中data 【】中的序号else //brow大小等于B.mut=B.tu+1;for(q=B.rops[brow];q<t;q++)//q为B中当前元素在B.data[]中的序号{ccol=B.data[q].j;//ccol:data[p]*data[q]所得结果所在的列temp[ccol]+=A.data[p].e*B.data[q].e;//temp【ccol】:相乘所得的C矩阵中第arow行cool列元素的值}}for(ccol=1;ccol<=B.nu;ccol++)//if(temp[ccol])//temp【ccol】不为零,则把值赋到c中,c.tu加1。

《数据结构——用C语言描述(第二版)》第5章 数组和广义表

《数据结构——用C语言描述(第二版)》第5章  数组和广义表
是指矩阵的下三角(不含对角线)中的元素均为常数C或零的n阶矩阵,下 三角矩阵则与之相反,如图5.3所示。
第五章 数组和广义表
在压缩存储时,矩阵中值相同的元素C可共享一个存储空间,元素 为零则可不必分配空间,而其余的元素有 n(n+1)/2个,因此三角矩阵 可用一维数组M[n×(n+1)/2+1]来存储,其中常数C放在数组的最后一 个下标变量中。
假设A和B矩阵分别用matrix型指针变量a和b表示,矩阵的转置可以 按以下进行:由于B的行是A的列,所以可按照b->data三元组表的次序在 a->data中找到相应的三元组进行转置,即可按a->data的列序转置,所得 到的转置矩阵B的三元组表b->data必定是按行优先存放的。因此,可以对 三元组表a->data从第一行起扫描,找到A的每一列中所有的非零元素,就 可以实现转置。
LOC ( aij ) =LOC ( a00) +(i×n+j) × c 同理可推导出以列为主序优先存储时数据元素a i j 的存储地址,其计算公式 为:
LOC( a i j ) =LOC( a00 ) +( j × n +i ) × c 对于三维数组Am×n×p而言,若以行为主序优先存储时,则其数据元 素aijk的存储地址可为: LOC ( a i j k) =LOC ( a000) +[ i × m×p +j ×p +k] × c 对于一般的二维数组A[c1…d1,c2…d2]而言,此处c1,c2的值不一定是 0,a i j 的地址为: LOC ( a i j ) =LOC ( a c 1 c 2 ) +[ ( i – c 1 )* ( d 2 – c 2 +1) +j – c 2 ] * c

数据结构实验报告_9

数据结构实验报告_9

本科生实验报告(二)姓名:学院:专业:班级:实验课程名称: 数据结构实验日期: 2013年 5月 25 日指导教师及职称:实验成绩:开课时间:2012~2013 学年第二学期k++;a[j][n-i-1]=k;}for (j=n-i-2;j>=i;j--){k++;a[n-i-1][j]=k;}for (j=n-i-2;j>=i+1;j--){k++;[j][i]=k;}}}void main(){int n,i,j;int a[MaxLen][MaxLen];printf("输入n(n<10):");scanf("%d",&n);fun(a,n);printf("%d阶数字方阵如下:\n",n);for (i=0;i<n;i++){for (j=0;j<n;j++)printf("%4d",a[i][j]);printf("\n");}}运行结果:6.2:如果矩阵A中存在这样的一个元素A[i][j]满足条件:A[i][j]是第i行中值最小的元素,且又是第j列中值最大的元素,则称为该矩阵的一个马鞍点。

设计一个程序exp6-2.cpp 计算出m*n的矩阵A的所有马鞍点。

主程序如下:6.3:已知A和B为两个n*n阶的对称矩阵,输入时,对称矩阵只输入下三角形元素,存入一维数组,如图6.5所示(对称矩阵M存储在一维数组A中),设计一个程序exp6-3.cpp 实习如下功能:(1)求对称矩阵A和B的和。

(2)求对称矩阵A和B的乘积。

A:图6.5 对称矩阵的存储转换形式主程序如下:#include <stdio.h>#define N 4#define M 10int value(int a[],int i,int j){if (i>=j)return a[(i*(i-1))/2+j];elsereturn a[(j*(j-1))/2+i];}void madd(int a[],int b[],int c[][N]){int i,j;for (i=0;i<N;i++)printf("a+b:\n");disp2(c1);printf("a×b:\n");disp2(c2);printf("\n");}运行结果:6.4::假设n*n的稀疏矩阵A采用三元组表示,设计一个程序exp6-4.cpp实现如下功能:(1)生成如下两个稀疏矩阵矩阵的三元组a和b:(2)输出a转置矩阵的三元组;(3)输出a+b的三元组;(4)输出a*b的三元组。

数组和广义表 数据结构

数组和广义表  数据结构

3.建立广义表的存储结构 假定广义表中的元素类型ElemType为chai类型,每个原子的值被限 定为英文字母。并假定广义表是一个表达式,其格式为:元素之间用一 个逗号分隔,表元素的起止符号分别为左、右圆括号,空表在其圆括号 内不包含任何字符。例如“(a,(b, c, d))”就是一个符合上述规定的广 义表格式。 建立广义表存储结构的算法同样是一个递归算法。该算法使用一个 具有广义表格式的字符串参数s,返回由它生成的广义表存储结构的头结 点指针h。在算法的执行过程中,需要从头到尾扫描s的每一个字符。当 碰到左括号时,表明它是一个表元素的开始,则应建立一个由h指向的表 结点,并用它的sublist域作为子表的表头指针进行递归调用,来建立子 表的存储结构;当碰到一个英文字母时,表明它是一个原子,则应建立 一个由h指向的原子结点;当碰到一个“)”字符时,表明它是一个空表, 则应置h为空。当建立了一个由h指向的结点后,接着碰到逗号字符时, 表明存在后继结点,需要建立当前结点(即由h指向的结点)的后继表; 当碰到右括号或分号字符时,表明当前所处理的表已结束,应该置当前 结点的link域为空。 4.输出广义表 5.广义表的复制
广义表的转换过程
为了使子表和原子两类结点既能在形式上保持一致,又能进
行区别,可采用如下结构形式:
其中,tag域为标志字段,用于区分两类结点。sublist或data
域由tag决定。若tag=0,表示该结点为原子结点,则第二个 域为data,存放相应原子元素的信息;若tag=l,表示该结点 为表结点,则第二个域为sublist,存放相应子表第一个元素 对应结点的地址。link域存放与本元素同一层的下一个元素所 在结点的地址,当本元素是所在层的最后一个元素时,link域 为NULL。 例:前面的广义表C的存储结构如下图所示(很多《数据结构 公教科书上称之为带表头结点的广义表的链表存储结构

数据结构Ch数组和广义表

数据结构Ch数组和广义表
//O(n)
✓ step4:扫描a.data,将(i,col,v)转置后放于b.data[pot[col]] 中,pot[col]++. //O(t)
时间O(n+t),快速。
key:pot[1..a.n]=第0~a.n-1列的非零元个数。
20
§5.2 矩阵的压缩存储
void FastTransMatrix(TripleTable &a , Tripletable &b) {//pot[0..a.n],比n多1 if (a.t == 0) Error(“…”);//A全零
11
§5.2 矩阵的压缩存储
3. 对角矩阵
总结:这类矩阵压缩存储后能找到地址计算公式, 使其保持随机存取的功能。
12
§5.2 矩阵的压缩存储
§ 5.2.2 稀疏矩阵
定义:设Amn中有t个非零元素,若 稀疏矩阵。
,称A为
稀疏因子: 压缩存储:
一般非零元素分布无规律性
只存储非零元,故须存储辅助信息,才能确 定其位置。
b.data[q].v = a.data[p].v;
}
}
21
§5.2 矩阵的压缩存储
以上图为例,
2. 带行表的三元组表。(顺序方式)
在行优先存储的三元组表中,加入一个行
表来记录稀疏矩阵压缩后每行非零元在三元组表
中的起始位置。
22
§5.2 矩阵的压缩存储
3. 十字链表 上两种方式是顺序存储,若非零元位置或个数经常发生 变化,会引起结点移动,效率降低。此时宜用链式存储。 例:A←A+B 稀疏矩阵的链接存储方式有多种,这里仅介绍十字链表
2
§5.1 多维数组
非线性特征 i th行:前驱aij-1,后继aij+1 j th列:前驱ai-1j,后继ai-1j 仅有一个开始结点:a11 仅有一个终端节点:amn 其他边界上的结点只有一个直接前驱或 一个直接后继,类似的m维数组 的 每一个元素都属于m个向量。

数据结构实践-第5周 串数组和广义表(复习)

数据结构实践-第5周 串数组和广义表(复习)

5.1 数组的定义
数组:按一定格式排列起来的 具有相同类型的数据元素的集合。
一维数组:若线性表中的数据元素为非结构的简单元素,
则称为一维数组。 一维数组的逻辑结构:线性结构。定长的线性表。 声明格式: 数据类型 变量名称[长度];
例:int num[5] = {0,1,2,3,4};
数据结构
第五周 串、数组和广义表
数据结构
第五周 串、数组和广义表
数据结构
第五周 串、数组和广义表
内容回顾1 1、 串的概念; 2、 串的存储结构; 3、 串的运算。
数据结构 4.1 串类型的定义 基本概念
第五周 串、数组和广义表
串(也称字符串):是由 0 个或多个字符组成的有限序列。 通常记为:s =― a1 a2 a3 … ai …an ‖ ( n≥0 )。 串的名 串的值 串的长度 字母、数字或其他字符
a00 a10 ……. am-1, 0 a01 a11 …….. am-1, 1 ………. a0, n-1 a1, n-1 …….. am-1, n-1
串的逻辑结构:和线性表极为相似。
区别:串的数据对象约定是字符集。 串的基本操作:和线性表有很大差别。 在线性表的基本操作中,大多以“单个元素” 作为操作对象; 在串的基本操作中,通常以“串的整体”作为 操作对象。例如:在串中查找某个子串、求 取一个子串、在串的某个位置上插入一个子 串以及删除一个子串等。
数据结构 以行序为主序存放:
第五周 串、数组和广义表 0 1
a00 a01 a00 a01 …….. a0, n-1 ……. a10 a11 …….. a1, n-1 a0, n-1 n -1 …………………. a10 n am-1, 0 am-1, 1 …….. am-1, n-1 a11 …….. 二维数组中任一元素 aij 的存储位置 a1, n-1 LOC(i, j) = LOC(0, 0) + (b2×i+j )×L ………. 基地址或基址 二维数组的映象函数 am-1, 0 am-1, 1 某个元素的地址就是它前面所有行 所占的单元加上它所在行前面所有列元 …….. m*n -1 素所占的单元数之和。 am-1, n-1

数据结构数组和广义表

数据结构数组和广义表

数据结构05数组与广义表数组与广义表可以看做是线性表地扩展,即数组与广义表地数据元素本身也是一种数据结构。

5.1 数组地基本概念5.2 数组地存储结构5.3 矩阵地压缩存储5.4 广义表地基本概念数组是由相同类型地一组数据元素组成地一个有限序列。

其数据元素通常也称为数组元素。

数组地每个数据元素都有一个序号,称为下标。

可以通过数组下标访问数据元素。

数据元素受n(n≥1)个线性关系地约束,每个数据元素在n个线性关系地序号 i1,i2,…,in称为该数据元素地下标,并称该数组为n维数组。

如下图是一个m行,n列地二维数组A矩阵任何一个元素都有两个下标,一个为行号,另一个为列号。

如aij表示第i行j列地数据元素。

数组也是一种线性数据结构,它可以看成是线性表地一种扩充。

一维数组可以看作是一个线性表,二维数组可以看作数据元素是一维数组(或线性表)地线性表,其一行或一列就是一个一维数组地数据元素。

如上例地二维数组既可表示成一个行向量地线性表: A1=(a11,a12,···,a1n)A2=(a21,a22, ···,a2n)A=(A1,A2, ···,Am) ············Am=(am1,am2, ···,amn)也可表示成一个列向量地线性表:B1=(a11,a21,···,am1)B2=(a12,a22, ···,am2)A=(B1,B2, ···,Bm) ············Bn=(a1n,a2n, ···,amn)数组地每个数据元素都与一组唯一地下标值对应。

数组和广义表学习

数组和广义表学习

中南大学《数据结构与算法》数组与广义表学习报告学习报告数组与广义表学习报告A 数组1学习目标:进一步深刻的了解数组的定义与运算,对数组的顺序存储结构更深入的认知。

也是对曾经学过的知识的进一步巩固。

更重要的是学习特殊矩阵的压缩存储方法实现矩阵之间的加减运算,如三角矩阵,对称矩阵,以及稀疏矩阵的一些基本操作。

2学习过程:数组是一种数据类型。

从逻辑结构上看,数组可以看成是一般线性表的扩充。

二维数组可以看成是线性表的线性表,应此可以利用线性表来存储多维数组。

把多维数组尤其是二维数组转换为线性表尤为重要,二维数组可以作为一个矩阵看待我们还可以将数组A m×n看成另外一个线性表:B=(β1,,β2,,… ,βm),其中βi(1≤i ≤m)本身也是一个线性表,称为行向量,即:βI= (a i1,a i2,…,a ij ,…,a in)。

这样把二维数组转换为了一维数组就能很轻松的进行操作与运算了。

数组的抽象数据类型定义(ADT Array)数据对象:D={ a j1j2…jn| n>0,称为数组的维数,j i是数组的第i维下标,1≤j i≤b i,bi为数组第i维的长度,a j1j2…jn∈ElementSet}基本操作:包括initArray(), destoryArray(), getElement(), setElement()1先实现了一位动态数组的存储#include<iostream>using namespace std;void main(){int *a ,n=10;int i;a=(int *)calloc(n,sizeof(int));for(i=0;i<n;i++)a[i]=i+1;for (i=0;i<n;i++)cout<<a[i]<<"\t";free(a);}通过实现了这个程序学到了更进一步的知道了如何动态申请内存空和释放动态深情的数组内存空间的calloc()函数,其函数原型为(void*)calloc(unsigned n ,sizeof(int))。

02331数据结构-04数组和广义表

02331数据结构-04数组和广义表

02331数据结构-04数组和广义表1.多维数组和广义表是一种复杂的非线性结构,它们的逻辑特征是:一个数据元素可能有多个直接前驱和多个直接后继。

2.一维数组(向量)是存储于计算机的连续存储空间中的多个具有统一类型的数据元素。

同一数组的不同元素通过不同的下标标识。

(a1,a2,…,an)3.二维数组Amn可视为由m个行向量组成的向量,或由n个列向量组成的向量。

二维数组中的每个元素aij既属于第i行的行向量,又属于第j列的列向量。

4.多维数组:三维数组Amnp可视为以二维数组为数据元素的向量。

四维数组可视为以三维数组为数据元素的向量……三维数组中的每个元素aijk都属于三个向量。

四维数组中的每个元素都属于四个向量……5.数组的顺序存储方式:由于计算机内存是一维的,多维数组的元素应排成线性序列后存人存储器。

数组一般不做插入和删除操作,即结构中元素个数和元素间关系不变化。

一般采用顺序存储方法表示数组。

(1)行优先顺序:将数组元素按行向量排列,第i+1个行向量紧接在第i个行向量后面。

【例】二维数组Amn的按行优先存储的线性序列为:a11,a12,…,a1n,a21,a22,…,a2n,……,am1,am2,…,amn(2)列优先顺序将数组元素按列向量排列,第i+1个列向量紧接在第i个列向量后面。

【例】二维数组Amn的按列优先存储的线性序列为:a11,a21,…,am1,a12,a22,…,am2,……,a1n,a2n,…,amn6.数组元素的地址计算公式:(1)按行优先顺序存储的二维数组Amn地址计算公式LOC(aij)=LOC(a11)+[(i-1)某n+j-1]某d(注:此公式下界为1,如下界为0,则公式变为[i某n+j])①LOC(a11)是开始结点的存放地址(即基地址)②d为每个元素所占的存储单元数③由地址计算公式可得,数组中任一元素可通过地址公式在相同时间内存取。

即顺序存储的数组是随机存取结构。

Chap5 数组与广义表

Chap5 数组与广义表

15 0 0 -7 0 0 0
随机稀疏矩阵的压缩存储方法:
一、三元组顺序表 二、 十字链表
一、三元组顺序表
对于非零元素在矩阵中随机出现的稀疏矩 阵,则在存储非零元素的同时,还必须存储该 非零元素在矩阵中所处的行号和列号。我们将 这种存储方法叫做稀疏矩阵的三元组表示法。
每个非零元素在一维数组中的表示形式 如图所示:
0 12 9 0 0 0 0 0 0 0 0 0 0 0 -3 0 0 0 0 14 0
M6 × 7 =
0 0 24 0 0 0 0
N7×6=
0 18 0 0 0 0 0
15 0 0 -7 0 0 0
0 12 9 0 0 0 0
0 0 0 0 0 0 0
-3 0 0 0 0 18 0 24 0 0 0 0 0 0 0 14 0 0 0 0 0
5.2 数组的顺序表示和实现
类型特点: 1)对于数组A,一旦给定其维数n及各维长度bi (1≤i≤n),则该数组中元素的个数是固定的, 不能对数组做插入和删除操作,不涉及移动元素 操作,因此数组采用顺序存储比较合适; 2) 数组是多维的结构,而存储空间是 一个一维 的结构, 因此有存储次序的约定问题。
L
二维数组Am*n中任一元素ai,j 的存储位置
LOC(i,j)=LOC(1,1) + (m×(j-1)+(i-1))×L
称为基地址或基址。
例:设有二维数组A[10][20],其每个元 素占2个字节,第一个元素A1,1的存储地址 为100,则按行优先顺序存储时元素A6,6的 存储地址为 A 6,6=100+[(6-1)*20+(6-1)]*2=310

ai2 ┇

i ┇ m

实验 二维数组和广义表

实验  二维数组和广义表

实验二维数组和广义表一、实验目的1.熟悉数组类型的实现2.掌握使用数组实现特殊矩阵的压缩存储3.掌握稀疏矩阵的三元组表示法的实现通过本次实习加深对高级语言C语言的使用,熟悉数组在C语言中的实现二、实验内容采用压缩顺序存储法,能够对于给定一组“合法”的下标(i,j)对应的元素a ij,进行存取运算;三、实验报告要求1.上机前完成所有的函数编写2.主要实验设备(软件)部分填写:装有TC软件的普通PC机3.实验记录部分填写编写主函数调用所写所有函数的屏幕输出4.设备名称填写PC机,型号可空,编号填写所使用计算机编号,运行情况填写良好5.实验总结部分写出AccessTSMatrix函数中i,j,k分别代表什么;main函数中i,r,c分别代表什么四、实验原理矩阵是很多的科学与工程计算中研究的数学对象。

在此,我们感兴趣的是,从数学结构这门学科着眼,如何存储矩阵的元从而使矩阵的各种运算有效的进行。

本来,用二维数组存储矩阵,在逻辑上意义是很明确的,也很容易理解,操作也很容易和方便。

但是在数值分析中经常出现一些阶数很高的矩阵,同时,在矩阵中又有很多值相同或者都为零的元素,可以对这种矩阵进行压缩存储:对多个值相同的元素只分配一个存储空间;对零元素不分配空间。

稀疏矩阵的定义是一个模糊的定义:即非零元个数较零元个数较少的矩阵。

例如下图所示的矩阵:012 9 0 0 0 000 0 0 0 0 030 0 0 0 14 000 24 0 0 0 0018 0 0 0 0 0150 0 -7 0 0 0为一个稀疏矩阵。

为了实现稀疏矩阵的这种存储结构,引入三元组这种数据结构。

三元组的线性表顺序存储形式如下图:行列值行列值行列值……行列值1 2 12 1 3 9 3 1 3 …… 6 4 -7五、参考程序算法思想:用线性表的顺序查找算法,在存储稀疏矩阵的数组中查找三元组中行列号(row,col)等于(i,j)的数组元素,若查找到,则可以通过数组元素的三元组中读取到元素的值val;若查找不到,则返回0参考程序:实验数据及结果:六、实验步骤1.参考实验程序自己编出程序,上机调试。

数据结构实验广义表

数据结构实验广义表

《数据结构》实验报告实验题目:广义表的创建与遍历实验目的:熟悉和掌握广义表的定义及结构,可以创建及遍历广义表。

实验内容:利用栈创建以及遍历一个广义表。

一、需求分析1.本演示程序中,输入广义表的内容应为任意符合广义表要求结构的数据,将数据输入创建广义表中,再通过遍历程序将其以广义表形式输出。

2.本程序是以用户与计算机的对话方式执行,运行程序后,按要求输入数据即可。

3.程序执行的命令包括:(1)构造广义表与链栈,并初始化(2)输入广义表(3)输出广义表(4)结束4.测试数据:输入((),((a,b),(c,d))) 输出((),((a,b),(c,d)))错误输入:如果输入((),((a,b),(c,d)))) 输出((),((a,b),(c,d)))二概要设计为了实现上述操作,应以广义链表为存储结构。

1.基本操作:Snode *Push(Snode *top,node *input)实现指针入栈Snode *Pop(Snode *top,node **output)实现指针出栈node *create()广义表的建立void print(node *head)广义表的输出2.本程序包括三个模块:(1)主程序模块(2)广义表的创建(3)广义表的遍历(4)入栈模块(5)出栈模块(6)模块调用图:三 详细设计1.元素类型、节点类型和指针类型//定义广义表typedef struct node{char data; /*存储数据*/int tag; /*用以标记,标记为1时为左括号,标记为0时为字符,标记为-1时为新开辟节点*/struct node *hp; /*该指针指向字表*/struct node *tp; /*该指针指向后续节点*/}node;//定义链栈typedef struct Snode{node *data;struct Snode *next;}Snode;Snode *topnode *inputSnode *sSnode *p;node **outputnode *p,*q,*head;2.每个模块的分析:(1) 主程序模块:int main(){node *head;printf("请输入广义表:\n");head=create();printf("该广义表为:\n");print(head);getchar();getchar();return 0;}(2)广义表的创建:node *create(){node *p,*q,*head; /*指针p是一个移动指针,指针q用以开辟新节点,head为头指针*/char x; /*输入字符*/Snode *top; /*栈顶指针*/top=NULL; /*栈顶置空*/q=(node *)malloc(sizeof(node)); /*申请新节点*/q->tag=1; /*广义表形式第一个字符必为左括号*/scanf("%c",&x); /*输入字符*/head=q; /*广义表头结点指向新开辟节点*/p=head; /*活动指针指向头结点*/top=Push(top,p); /*该节点指针入栈*/q=(node *)malloc(sizeof(node)); /*开辟新节点*/q->tag=-1; /*新节点标记为-1*/p->hp=q; /*上一个读到的是左括号,将新节点链到当前节点的子表*/p->tag=1; /*当前节点为左括号,标记为1*/p->data=NULL; /*当前节点数据域为空*/p=p->hp; /*活动指针移到当前节点的子表*/scanf("%c",&x); /*接着输入数据*/while(top!=NULL) /*遇到左括号进栈,右括号退栈,栈空循环结束*/{if(x=='(') /*遇到左括号*/{q=(node *)malloc(sizeof(node)); /*申请新节点*/q->tag=-1; /*新节点标记均为-1*/p->hp=q; /*新节点链到当前节点的子表*/p->tag=1; /*因是左括号,当前节点标记为1*/p->data=NULL; /*数据域为空*/top=Push(top,p); /*指针入栈*/p=p->hp; /*移动指针到当前节点的子表*/}else if(x==',') /*遇到逗号*/{q=(node *)malloc(sizeof(node)); /*申请新节点,标记-1*/q->tag=-1;p->tp=q; /*新节点链到当前节点后续节点*/p=p->tp; /*移动指针到当前节点的后续*/}else if(x==')') /*遇到右括号*/{p->tp=NULL; /*后续域置空*/top=Pop(top,&p); /*栈顶指针退栈*/ }else /*遇到其他字符*/{p->tag=0; /*标记为0*/p->data=x; /*数据域存数据*/p->hp=NULL; /*子表指向置空*/ }scanf("%c",&x); /*再读下一个字符*/ }p->tp=NULL; /*循环结束,当前节点后续置空*/return(head);(3)广义表的遍历:void print(node *head){node *p;Snode *top;p=head;top=NULL; /*栈置空*/while(p!=NULL||top!=NULL) /*p空且栈空时退出循环*/{if(p!=NULL) /*如果活动指针不空,做三个判断*/{if(p->tag==1) /*标记为1输出左括号,指针进栈,活动指针下移*/{top=Push(top,p);printf("(");p=p->hp;}else if(p->tag==0) /*标记为0,输出字符,如果后续不空,输出逗号*/{printf("%c",p->data);if(p->tp!=NULL){printf(",");}p=p->tp;}else if(p->tag==-1) /*标记为-1,先出栈,出栈后p上移输出右括号,如果后续不空,输出逗号*/{top=Pop(top,&p);printf(")");if(p->tp!=NULL){printf(",");}p=p->tp;}}else /*若p空,表示该层结束*/{top=Pop(top,&p); /*退栈,指针上移,若上移后仍不为空,且此时栈必定不空,输出右括号*/printf(")");if(p->tp!=NULL) /*若后续不为空,需输出逗号,指针后移*/{printf(",");}p=p->tp;}}printf("\n");}(4)入栈模块:Snode *Push(Snode *top,node *input){Snode *s;s=(Snode *)malloc(sizeof(Snode)); /*申请新节点*/s->data=input;s->next=top;top=s;return(top);}(5)出栈模块:Snode *Pop(Snode *top,node **output){Snode *p;if (top==NULL){*output=NULL;return NULL;}else{*output=top->data;p=top;top=top->next;free(p);return(top);}}3.完整的程序:(见源文件).四使用说明、测试分析及结果1.程序使用说明:(1)本程序的运行环境为VC6.0。

数据结构实验:广义表

数据结构实验:广义表

广义表实验:广义表基本操作实现实验目的:1、熟悉的存储方式;2、通过实验,深入理解递归以及广义表中的递归实现;实验要求:1、在vc++或tc环境下实现基本功能;2、先完成基本功能,基本功能为必做内容,有多余时间的同学可以做选做的内容;3、独自完成实验操作,并给出相关的数据;4、每次实验后,撰写实验报告,并在下星期一由学习委员收集并按学号整理好后,交任课教师。

实验内容及步骤:必做题:1、由字符串构建一个广义表;2、输出该广义表;3、求广义表的长度和深度;选做:1、求广义表的表头、表尾;2、输出广义表的所有的原子,并求该广义表中的最大原子;附:程序可以使用参考的,更提倡自己编写,使用参考程序的同学把函数的功能读懂,并用实例去走一遍。

参考程序:#include"stdio.h"#include"malloc.h"typedef char elemtype;typedef struct lnode{int tag;union{elemtype data;struct lnode *sublist;}val;struct lnode *link;}glnode;glnode *creatgl(char *&s){glnode *h;char ch;ch=*s;s++;if(ch!='\0'){h=(glnode *)malloc(sizeof(glnode));if(ch=='('){h->tag=1;h->val.sublist=creatgl(s);}else if(ch==')')h=NULL;else{h->tag=0;h->val.data=ch;}}else h=NULL;ch=*s;s++;if(h!=NULL)if(ch==',')h->link=creatgl(s);elseh->link=NULL;return h;}int gllength(glnode *g) {int n=0;g=g->val.sublist;while(g){n++;g=g->link;}return n;}int gldepth(glnode *g) {int max=0,dep;if(g->tag==0)return 0;g=g->val.sublist;if(g==NULL)return 1;while(g){if(g->tag==1){dep=gldepth(g);if(dep>max)max=dep;}g=g->link;}return(max+1);}void dispgl(glnode *g){if(g){if(g->tag==1){printf("(");if(g->val.sublist==NULL)printf("");elsedispgl(g->val.sublist);}elseprintf("%c",g->val.data);if(g->tag==1)printf(")");if(g->link){printf(",");dispgl(g->link);}}}void main(){glnode *g;char *s="(a,(b,c),d,(e,(f,g)))";g=creatgl(s);printf("输出广义表g:");dispgl(g);printf("\n");printf("输出广义表g的长度:");printf("%d\n",gllength(g));printf("输出广义表g的深度:");printf("%d\n",gldepth(g));}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《数据结构》实验报告
实验序号: 7实验项目名称:数组和广义表
学号姓名专业班级
实验地点指导教师实验时间
一、实验目的及要求
本次实验目的是通过上机练习,熟悉和掌握课堂所讲授的基本知识点。

要求
上机以前要认真复习课堂教学内容。

完成稀疏矩阵的三元组顺序存储。

二、实验设备(环境)及要求
计算机;学生不许把食物带到机房吃;不许上网做与实验无关的内容;不许
同学之间聊天;保持实验室安静卫生。

下课把键盘,座椅放回原处。

三、实验内容与步骤
稀疏矩阵压缩存储,三元组顺序表的实现。

然后完成操作CreateSMatrix(&M) 创建稀疏矩阵,和求稀疏矩阵的转置 TransposeSMatrix(TSMatrix &M, TSMatrix &T) 。

编写一个函数,按照矩阵的形式打印出稀疏矩阵。

Header.h
#include<stdio.h>
#include<stdlib.h>
//稀疏矩阵的三元组顺序表存储
#define MAXSIZE 125 //非零元个数的最大值
typedef int ElemType;
typedef struct//三元组节点
{
int i,j;//非零元的行下标、列下标
ElemType e;//矩阵的元素值。

}Triple;
typedef struct
{
Triple data[MAXSIZE+1];//非零元数组,data[0]不用。

int mu,nu,tu;//矩阵的行数、列数、非零元个数。

}TSMatrix;
//-------稀疏矩阵的操作函数-------//
void CreateSMatrix(TSMatrix *M)
//以行为主序,创建稀疏矩阵
{
char sign='y';
int tu;
(*M).tu=0;(*M).mu=0;(*M).nu=0;
printf("请输入矩阵的行数: \n");
scanf("%d",&(*M).mu);
printf("请输入矩阵的列数: \n");
scanf("%d",&(*M).nu);
while(sign=='y')
{
++(*M).tu;
tu=(*M).tu;
printf(" 请输入第 %d个非零元 \n",tu);
printf("\n请输入行号: ");
scanf("%d",&(*M).data[tu].i);
printf("\n请输入列号: ");
scanf("%d",&(*M).data[tu].j);
printf("\n请输入元素值: ");
scanf("%d",&(*M).data[tu].e);
printf("\n\n如果继续输入其他非零元素,请输入字母'y' ,否则请输入 'n' : ");
scanf("%c%c",&sign,&sign);
}
}
void PrintSMatrix(TSMatrix *M)
{
int *p,k,i,j;
int mu,nu,tu;
mu=(*M).mu;nu=(*M).nu;tu=(*M).tu;
p=(int *)malloc((nu+1)*sizeof(ElemType));//用来保存每行元素。

for(i=1;i<=mu;i++)
{
for(k=0;k<=nu;k++) p[k]=0;
for(k=1;k<=tu;k++)
{
if((*M).data[k].i==i)
p[(*M).data[k].j]=(*M).data[k].e;
}
for(j=1;j<=nu;j++) printf("%-5d",p[j]);
printf("\n");
}
}
void TransposeSMatrix(TSMatrix *M,TSMatrix *T) //采用三元组表存储,实现稀疏矩阵的转置。

{
int q=1,col=1;
(*T).mu=(*M).nu;
(*T).nu=(*M).mu;
(*T).tu=(*M).tu;
for(col=1;col<=(*M).nu;col++)
{
for(q=1;q<=(*M).tu;q++)
if((*M).data[q].j==col)
{
(*T).data[q].i=(*M).data[q].j;
(*T).data[q].j=(*M).data[q].i;
(*T).data[q].e=(*M).data[q].e; }
}
}
Source.h
#include"header.h"
void main()
{
TSMatrix M,T;
CreateSMatrix(&M); PrintSMatrix(&M); TransposeSMatrix(&M,&T); printf("\n\n");
PrintSMatrix(&T);
四、实验结果与数据处理
五、分析与讨论
以前学过另一种将矩阵转置的方法,现在学习的这种方法更方便,遇到复杂、阶数比较大的有规律的矩阵,存储更省内存。

这种方法更具有一般性,能学到这种通用的方法大大减轻了计算量,感觉很好。

六、教师评语成绩
签名:
日期:。

相关文档
最新文档