1 / 46

第五章 数组与广义表

第五章 数组与广义表. 5.1 数组的定义 5.2 数组的顺序表现和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的存储结构 5.6 广义表的递归算法. 5.1 数组的定义. 数组: 按一定格式排列起来的一列同一属性的项目 , 是相同类型的数据元素的集合。有一维数组 A[5] 、二维数组 A[5][5] 、三维数组 A[5][5][5] 、多维数组等。 二维数组: 每一行都是一个线性表,每一个数据元素既在一个行表中,又在一个列表中。. 5.2 数组的顺序表现和实现. 二维数组以 行 为主的顺序存储

agnes
Download Presentation

第五章 数组与广义表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第五章 数组与广义表 5.1 数组的定义 5.2 数组的顺序表现和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的存储结构 5.6 广义表的递归算法

  2. 5.1 数组的定义 • 数组:按一定格式排列起来的一列同一属性的项目,是相同类型的数据元素的集合。有一维数组A[5]、二维数组A[5][5]、三维数组A[5][5][5]、多维数组等。 • 二维数组:每一行都是一个线性表,每一个数据元素既在一个行表中,又在一个列表中。

  3. 5.2 数组的顺序表现和实现 • 二维数组以行为主的顺序存储 Loc(aij)=Loc(a11)+[(i-1)n+(j-1)]*L 其中 L=sizeof(datatype)

  4. 2. 二维数组以列为主的顺序存储 其中 L=sizeof(datatype)

  5. Loc(aij)=Loc(a11)+[(i-1)n+(j-1)]*L • Loc(aij)=Loc(a11)+[(j-1)m+(i-1)]*L

  6. 5.3 矩阵的压缩存储 下三角矩阵: A为N*N阶方阵 存储方式: 1.按行存储 2.按列存储 3.压缩存储

  7. 用长度为n(n+1)/2的一维数组B, 一行接一行存放A中下三角部分的元素。

  8. 用长度为n(n+1)/2的一维数组B, 一列接一列存放A中下三角部分的元素。

  9. 2.对称矩阵的压缩存储

  10. 3.三对角矩阵的压缩存储

  11. 用一个长度为3n-2的一维数组B存放三条对角线上的元素用一个长度为3n-2的一维数组B存放三条对角线上的元素

  12. 4.一般稀疏矩阵的表示 • 稀疏矩阵的三列二维数组表示 • 十字链表

  13. 稀疏矩阵的三列二维数组表示

  14. (1)非零元素所在的行号i; (2)非零元素所在的列号j; (3)非零元素的值V。 即每一个非零元素可以用下列三元组表示: (i,j,V)

  15. (1,3,3) (1,8,1) (3,1,9) (4,5,7) (5,7,6) (6,4,2) (6,6,3) (7,3,5)

  16. (7,8,8) (1,3,3) (1,8,1) (3,1,9) (4,5,7) (5,7,6) (6,4,2) (6,6,3) (7,3,5)

  17. POS(k)表示稀疏矩阵A中第k行的第一个非零元素 (如果有的话)在三列二维数组B中的行号; NUM(k)表示稀疏矩阵A中第k行中非零元素的个数。 POS(1)=2 POS(k)=POS(k-1)+NUM(k-1) , 2≤k≤m

  18. 构造POS与NUM向量 输入:与稀疏矩阵A对应的三列二维数组B。 输出:POS与NUM向量。 PROCEDURE POSNUM(B,POS,NUM) t=B(1,3) [非零元素个数] m=B(1,1) [稀疏矩阵行数] FOR k=1 TO m DO NUM(k)=0 [置NUM向量初值] FOR k=2 TO t+1 DO NUM(B(k,1))=NUM(B(k,1))+1[设置NUM向量] POS(1)=2 FOR k=2 TO m DO POS(k)=POS(k-1)+NUM(k-1) [设置POS向量] RETURN

  19. 矩阵转置

  20. 输入:稀疏矩阵A的三列二维数组表示。 输出:转置矩阵D(三列二维数组表示)。 PROCEDURE TRAN(A,D) k=A(0,2) [转置稀疏矩阵B的行数] t=A(0,3) [非零元素个数] D(0,1)=k; D(0,2)=A(0,1); D(0,3)=A(0,3) [置转置矩阵信息] IF (t=0) RETURN kk=1

  21. for (m=1/0; m<=k/k-1; m++) for (n=1; n<=t; n++) { if (a[n].j==m) { d[kk].i=a[n].j; d[kk].j=a[n].i; d[kk].v=a[n].v; kk=kk+1; } } return; } struct ab { int i; int j; ET v;}; tran(a,d) struct ab *a, *d; { int k,t,kk,m,n; k=a[0].j; t=(int)(a[0].v); d[0].i=k; d[0].j=a[0].i; d[0].v=a[0].v; if (t==0) return; kk=1;

  22. 十字链表

  23. 用十字链表表示稀疏矩阵的结构特点 (1)稀疏矩阵的每一行与每一列均用带表头结点的循环链 表表示。 (2)表头结点中的行域与列域的值均置为0 (即row=0,col=0)。 (3)行、列链表的表头结点合用,且这些表头结点通过值 域(即val)相链接,并再增加一个结点作为它们的 表头结点H,其行、列域值分别存放稀疏矩阵的行数 与列数。 只要给出头指针H的值,便可扫描到稀疏矩阵中的任意一个非零元素。

  24. 十字链表的矩阵相加 #include <stdio.h> struct node { int row, col, val; struct node * right, * down}; typedef struct node NODE; NODE * a, * b, * c; NODE * create_null_mat(m,n) int m, n; { NODE *h, * p, * q; int k; h = (NODE*)malloc (sizeof(NODE) ); h->row =m; h->col= n;h->val=0; h->right=h; h->down=h; p=h; for (k=0; k<m; k++ ) {q=(NODE*)malloc(sizeof(NODE) ); q->col=1000;q->right=q; q->down=p->down; p->down=q; P=q;} p=h; for (k=0;k<n;k++ ) {q=(NODE * )malloc (sizeof(NODE) ); q->row=1000 ; q->down=q; q->right=p->right ; p->right=q; p=q;} return(h); }

  25. NODE * search_row_last( a , i) NODE *a ; int i; { NODE *p, *h; int k; p = a ;for (k=0; k<=i; k ++) p = p->down; h=p;while (p->right!=h) p = p->right; return (p); }

  26. NODE *search_col_last(a,j) NODE * a ; int j; { NODE * p, * h; int k: p = a; for (k=0; k<=j; k++) p=p->right; h=p; while (p->down !=h) p=p->down; return (p); }

  27. void insert_node(a,row,col,value). NODE * a; int row, col, value; { NODE * p, * q, * r; p =search_row_last (a, row ); q =search_col_last(a,col); r= (NODE * )malloc(sizeof(NODE)); r->row=row; r->col=col; r->val=value; r->right=p->right ; p->right=r; r->down=q->down; q->down=r; a->val++; }

  28. NODE *create_mat() { int m, n, t, i, j, k, v ; NODE * h; printf (" Input 3 --tuples: \n" ) ; printf(" % 3d: ", 0); scanf(" %d, %d, %d", &m,&n,&t); h=create_null_mat(m,n); for (k=1; k<=t; k++ ) { printf(" %3d: ",k); scanf(" %d, %d, %d",&i,%j,&v); insert_node(h,i,j, v ); } return (h ); }

  29. NODE * mat_add(a,b) NODE * a, * b; { NODE *c, *p, *q, *u, *v; c = create_null_mat (a->row, a->col); p = a->down; u =b->down; while (p!=a) { q = p->right; v=u->right; while (q != p || v != u) {if ( q->col = = v->col) { if (q->val + v->val != 0) insert_node (c,q->row, q->col, q->val+v->val ); q=q->right ; v=v->right; } • else if (q->col<v->col ) • { insert_node (c, q->row, • q->col, q->val ); • q=q->right; } • else { insert_node(c, • v->row, v->col, v->val ); • v=v->right; } } • p=p->down; u = u->down;} • } return (c ); }

  30. NODE * mat_add(a,b) • NODE * a, * b; • { NODE *c, *p, *q, *u, *v; • c = create_null_mat (a->row, • a->col); • p=a->down; u =b->down; • while (p!=a) • {q=p->right; v=u->right; • while (q!=p||v!=u) • {if (q->col==v->col) • { if (q->val+v->val!=0) • insert_node (c,q->row,q->col, • q->val+v->val); • q=q->right ; v=v->right; • } • else • if (q->col<v->col ) • { insert_node (c, q->row, • q->col, q->val ); • q=q->right; } • else { insert_node(c, • v->row, v->col, v->val ); • v=v->right; } • } • P=p->down; u = u->down; • } • return (c ); • }

  31. 5.4 广义表的定义 • 定义: (列表)n ( n 0 )个元素有限序列,记作 • A = (d1, d2, d3, …, dn) • A是表名,di是表元素,可以是数据元素(称为原子或单元素),也可以是表 (称为子表) • n为表的长度, n = 0 的广义表为空表 • n > 0时,表的第一个元素d1称为广义表的表头(head),除此之外,其它元素组成的表 (d2, d3, …, dn)称为广义表的表尾(tail )

  32. A是空表,长度为0 B只有一个原子,长度为1 C长度为2,一个原子和子表 D长度为3,三个子表 E长度为2,递归表 小写:原子;大写:子表 例: A = ( ) 深度:1 B = ( e ) 深度:1 深度:2 C = ( a, ( b, c, d ) ) D = (A , B, C ) D = (( ), ( e ), ( a, ( b, c, d ) ) ) 深度:3 E = ( a, E ) E = (a, ( a, ( a, …) ) ) 深度: 展开后所含括号的层次数 • 广义表特性 有次序性 有深度(层次) 可共享  可递归 长度为0,空表 • A()与A(())不同 • 任一非空广义表的表头可能是原子或子表;表尾必定是子表 长度为1,表头与表尾均为()

  33. tag =1 dlink link tag =0 data link 表结点 原子结点 • 5.5 广义表的存储结构 • 结点定义 指向含子表第一个元素的结点 typedef struct GLNode { int tag; union { DataType data; struct GLNode *dlink; }dd; struct GLNode *linkp; }GList; 指向本层下一个结点

  34. A = ( )   A 1  B = ( e ) B 1 C = ( a, ( b, c, d ) )  e 0 D = (A , B, C ) E = ( a, E )  C 1  a 1 0 b c d  0 0 0  D 1    E 1 1 1 1 a  0 1 删除某子表第一个结点

  35. A = ( )   A 1 B = ( e ) C = ( a, ( b, c, d ) )  C 1 D = (A , B, C )  a 1 0 E = ( a, E ) 1 b c d  0 1 0 0  B 1  e 1 0  E 1  a  D 1 1 0 1   1 1 1 1 每个子表增设表头结点 tp指向含第一个元素的结点 hp留作自用

  36. tag =1 dlink link tag =0 data link 表结点 原子结点   5.6 广义表递归算法的实现 #include <stdio.h> struct node { int tag; union { struct node *dlink; char data; } dd; struct node *link; }; typedef struct node NODE;

  37.  p 1 1 q   a a 1 1 0 0 b b c c d d   0 0 0 0 0 0 NODE *copy(p) NODE * p; { NODE *q; if (P==NULL) return(NULL); q=(NODE * )malloc (sizeof(NODE)); q->tag = p->tag; if (p->tag) q->dd.dlink=copy(p->dd.dlink); else q->dd.data=p->dd.data; q->link=copy(p->link); return(q); }

  38.  s t 1 1   a a 1 1 0 0 b b c c d d   0 0 0 0 0 0 int equal(s,t) NODE *s, *t; { int x; if (s==NULL&& t==NULL) return(1); if (s!=NULL && t!=NULL) if (s->tag==t->tag) { if (!s->tag) if (s->dd.data==t->dd.data) x=1; else x=0; else x=equal(s->dd.dlink, t->dd.dlink); if (x) return(equal(s->link,t->link));} return(0); }

  39. 练习 1. 写出顺序存贮的栈置空,进栈,出栈的算法。 2. 写出链接存贮的栈置空,进栈,出栈的算法。 3、写出二分法顺序查找存序表的算法。 4、写出f(n)=n!的递归算法,并画出4!的栈的变化过程 5、写出求 g(m,n)= 0 (当m=0,n>=0时),g(m,n)=g(m-1,2n)+n (当m>0,n>=0时)的递归算法,并画出g(5,2) 时的栈的变化过程。­­­­­­­­­ 6、假设以带头结点的循环链表表示队列,并且只设一个指针指向队列的尾部,不设头指针试编写相应的置空队列,入队列,和出队列的算法。

  40. 7、设有一个单向循环链表,其结点含三个域|:pre,data,next,其中data是数据域,next为指针域,其值为后继结点的地址,pre也为指针域,值为空­(null) ,试编写算法将此链表改为双向链表。 8、设A=(a0 ,a1,a2,….am-1) B=(b0,b1,……bn-1) 均为线性表,若A’,B’为删去最大共同前缀后的子表, (例如A=(x,y,y,z,x,z), B=(x,y,y,z,y,x,x,z) 则二者最大共同前缀为x,y,y,z,,在两表中除去最大共同前缀后的子表为A’=(x,z),B’=(y,x,x,z),) 若A’=B’=空表,则A=B, 若A’=空表,B’<>空表,或两者均不空,且A’的首元小于B’的首元,则A<B,否则A>B。试写一个比较A B大小的算法。 9、试以循环链表作稀疏多项式的存贮结构,编写求其导函数的算法。

More Related