1 / 53

第五章 数组和广义表

第五章 数组和广义表. 学习要点 1 .了解数组的两种存储表示方法,并掌握数组在以行为主的存储结构中的地址计算方法。 2 .掌握对特殊矩阵进行压缩存储时的下标变换公式。 3 .了解稀疏矩阵的两种压缩存储方法的特点和适用范围,领会以三元组表示稀疏矩阵时进行矩阵运算采用的处理方法。 4 .掌握广义表的结构特点及其存储表示方法。.  第四章 数组和广义表 5 .1 数组的定义和特点 5 .2 数组的顺序存储结构和实现 5 .3 矩阵的压缩存储 5 .4 广义表. 返回主菜单.

chana
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. 第五章 数组和广义表

  2. 学习要点 1.了解数组的两种存储表示方法,并掌握数组在以行为主的存储结构中的地址计算方法。 2.掌握对特殊矩阵进行压缩存储时的下标变换公式。 3.了解稀疏矩阵的两种压缩存储方法的特点和适用范围,领会以三元组表示稀疏矩阵时进行矩阵运算采用的处理方法。 4.掌握广义表的结构特点及其存储表示方法。

  3.  第四章 数组和广义表 5.1 数组的定义和特点 5.2 数组的顺序存储结构和实现 5.3 矩阵的压缩存储 5.4 广义表 返回主菜单

  4. ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 数组可以看成是一种特殊的线性表,即线性表中数据元素本身也是一个线性表 • 5.1 数组的定义和特点 • 定义 n维数组中含有多少个数据元素? • 数组特点 • 数组结构固定 • 数据元素同构 • 数组运算 • 给定一组下标,存取相应的数据元素 • 给定一组下标,修改数据元素的值

  5. a11 0 0 1 a12 按行序为主序存放 a11 按列序为主序存放 1 ……. a21 a1n n-1 ……. a21 m-1 n am1 m a22 a11 a12 …….. a1n a11 a12……..a1n a12 …….. a21 a22 …….. a2n a21 a22 ……..a2n a22 a2n …….. …………………. …………………. ………. am2 am1 am1 am2 …….. amn am1am2…….. amn ………. am2 a1n Loc( aij)=Loc(a11)+[(i-1)n+(j-1)]*l …….. Loc(aij)=Loc(a11)+[(j-1)m+(i-1)]*l a2n m*n-1 amn …….. m*n-1 amn 多维——〉一维 • 5.2 数组的顺序存储结构和实现 • 次序约定 • 以行序为主序 • 以列序为主序

  6. a11 a12….… ….. a1n a21a22…….. ……. a2n …………………. an1an2…….. ann 按行序为主序: …... a11 a21 a22 a31 a32 an1 ann …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 ? • 对称矩阵 • 5.3 矩阵的压缩存储

  7. a11 0 0…….. 0 a21 a220…….. 0 …………………. 0 an1 an2 an3…….. ann 按行序为主序: …... a11 a21 a22 a31 a32 an1 ann …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 i(i-1) Loc(aij)=Loc(a11)+[( +(j-1)]*l 2 • 三角矩阵

  8. a11a12 0 …………… . 0 a21 a22a230…………… 0 0a32 a33a340……… 0 …………………………… 00… an-1,n-2 an-1,n-1an-1,n 00… …an,n-1 ann. …... a11 a12 a21 a22 a23 ann-1 ann 按行序为主序: …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 • 对角矩阵 Loc(aij)=Loc(a11)+2(i-1)+(j-1)

  9. 如何进行稀疏矩阵的压缩存储? ? • 稀疏矩阵 • 定义:非零元较零元少,且分布没有一定规律的矩阵 • 压缩存储原则:只存矩阵的行列维数和每个非零元的行列下标及其值 表示非零元的 三元组 M由{(1,2,12), (1,3,9), (3,1,-3), (3,6,14), (4,3,24), (5,2,18), (6,1,15), (6,4,-7) } 和矩阵维数(6,7)唯一确定

  10. 非零元值 行列下标 i j v 0 1 2 3 4 5 6 7 8 ma #define MAXSIZE 20 typedef struct node { int i,j; int v; }JD; JD ma[M]; • 稀疏矩阵的压缩存储方法 • 顺序存储结构 • 三元组表 678 1 2 12 ma[0].i,ma[0].j,ma[0].v分别存放 矩阵行列维数和非零元个数 1 3 9 3 1 -3 3 6 14 4 3 24 三元组表所需存储单元个数为3(t+1) 其中t为非零元个数 5 2 18 6 1 15 6 4 -7

  11. • 求转置矩阵 • 问题描述:已知一个稀疏矩阵的三元组表,求该矩阵转置矩阵的三元组表 • 问题分析 常规的二维数组表示时转置的算法: for(col=1;col<=nu;++col) for(row=1;row<=mu;++row) T[col][row]=M[row][col]; T(n)=O(munu)

  12. 768 678 i j e i j e 1 3 -3 1 2 12 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 1 6 15 1 3 9 N.data 2 1 12 3 1 -3 M.data 2 5 18 3 6 14 ? 3 1 9 4 3 24 3 4 24 5 2 18 4 6 -7 6 1 15 6 3 14 6 4 -7

  13. 0 0 3 0 0 15 - 12 0 0 0 18 0 9 0 0 24 0 0 = T - 0 0 0 0 0 7 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 × 7 6 稀疏矩阵三元组转置算法 解决思路:只要做到 将矩阵行、列维数互换 将每个三元组中的i和j相互调换 重排三元组次序,使T.data中元素以T的行(M的列)为主序 方法一:按M的列序转置 ? • 算法思想: 按T.data中三元组次序依次在M.data中找到相应的三元组进行转置。 为找到M中每一列所有非零元素,需对其三元组表M.data从第一行起扫描一遍。

  14. i j e i j e 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 p p p p p p p p p k k p k p k p p p p k p 678 1 2 12 1 3 9 3 1 -3 0 0 3 0 0 15 - 3 6 14 12 0 0 0 18 0 M.data T.data 4 3 24 9 0 0 24 0 0 = T - 5 2 18 0 0 0 0 0 7 6 1 15 0 0 0 0 0 0 0 0 14 0 0 0 6 4 -7 0 0 0 0 0 0 × 7 6 768 1 3 -3 1 6 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14 col=1 col=2

  15. 算法分析:T(n)=O(M的列数n非零元个数t) 若 t 与mn同数量级,则 • 算法描述: Status TransposeSMatrix(TSMatrix M, TSMatrix &T) { T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; if (T.tu) { q=1; } return OK; }//TransposeSMatrix 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;}

  16. 1 3 -3 1 6 15 678 1 2 12 2 5 18 1 3 9 3 1 9 3 1 -3 0 0 3 0 0 15 3 4 24 - 3 6 14 12 0 0 0 18 0 4 6 -7 4 3 24 9 0 0 24 0 0 6 3 14 = T - 5 2 18 0 0 0 0 0 7 6 1 15 0 0 0 0 0 0 0 0 14 0 0 0 6 4 -7 0 0 0 0 0 0 × 7 6 方法二:稀疏矩阵的快速转置 • 算法思想:以M矩阵的三元组为中心, 依次取出 M.data 中的每一个三元组,交换行列后,直接将其写入T.data合适的位置中。 i j e i j e 768 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 2 1 12 如果能先求得M各列 第一个非零元三元组在T.data 中的位置 就能在对M.data一次扫描的过程中, 完成M到T的转置 T.data M.data

  17. cpot[1]=1; cpot[col]=cpot[col-1]+num[col-1]; (2≤col ≤M.nu) col 3 6 7 1 2 4 5 2 num[col] 1 0 2 2 1 0 cpot[col] 实现:引入两辅助数组 num[col]:存储矩阵M中第col列中非零元个数 cpot[col]:存储M中第col列第一个非零元在T.data中位置 显然有: 5 8 9 1 3 7 8

  18. 快速转置算法主要步骤: 1、求 M 中各列非零元个数num[ col]; 2、 求 M中各列第一个非零元在T.data 中的位置 cpot[col ]; 3、 对 M.data 进行一次扫描, 遇到 col 列的第一个非零元三元组时,按cpot[col ]的位置,将其放至 T.data 中,当再次遇到各列后续的非零元三元组时,只需顺序放到对应列元素的后面;

  19. i j e 0 1 2 3 4 5 6 7 8 p p p p p p p p i j e 0 1 2 3 4 5 6 7 8 678 1 2 12 1 3 9 3 1 -3 col 7 5 1 2 3 4 6 3 6 14 T.data num[col] 0 2 2 2 1 1 0 4 3 24 9 cpot[col] 8 5 8 7 3 1 5 2 18 6 1 15 6 4 -7 M.data 快 速 转 置 过 程 6 4 2 9 3 5 7 各列第一个 非零元三元组按已求出的位置放到T.data中 768 1 3 -3 1 6 15 2 1 12 2 5 18 各列后续的非零元三元组,顺序放到对应列元素的后面 3 1 9 3 4 24 4 6 -7 6 3 14

  20. 算法描述: Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){ T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; } return OK;}//FastTransposeSMatrix 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]; }

  21. 678 768 i j e i j e 1 2 12 1 3 -3 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 1 3 9 1 6 15 T.data 3 1 -3 2 1 12 M.data col 7 2 4 5 1 6 3 3 6 14 2 5 18 num[col] 0 1 0 1 2 2 2 4 3 24 3 1 9 9 cpot[col] 7 8 8 1 3 5 5 2 18 3 4 24 6 1 15 4 6 -7 6 4 -7 6 3 14 • 算法分析:T(n)=O(M的列数n+非零元个数t) 若 t 与mn同数量级,则T(n)=O(mn)

  22. 行逻辑链接的顺序表 有时为了方便某些矩阵运算,我们在按行优先存储的三元组中,加入一个行表来记录稀疏矩阵中每行的非零元素在三元组表中的起始位置。当将行表作为三元组表的一个新增属性加以描述时,我们就得到了稀疏矩阵的另一种顺序存储结构:“带行链接信息”的三元组表。 其类型描述如下:

  23. #define maxsize 100 typedef struct{ triple data[maxsize+1];//非零元三元组表 int rpos[maxrc+1]; //各行第一非零元的位置表 int n,m,t; //矩阵的行、列数和非零元个数 }TSMatrix; 下面讨论两个稀疏矩阵相乘的例子,容易看出这种表示方法的优越性。

  24. 两个稀疏矩阵相乘 两个矩阵相乘的经典算法也是大家所熟悉的。 若设 Q=M*N 其中,M是m1*n1矩阵,N是m2*n2矩阵。 常规的二维数组表示时转置的算法: 当n1=m2时,有: for(i=1;i<=m1;++i) for(j=1;j<=n2;++j){ q[i][j]=0 for(k=1;k<=n1;++k) q[i][j]+=m[i][k]*n[k][j]; } 此算法的复杂度为O(m1*n1*n2)。

  25. 如何从M和N求得Q呢? 行逻辑链接的顺序表 • 算法思想: 1、求乘积矩阵Q中元素 由矩阵乘法规则知: Q(i,j)=M(i,1)×N(1,j)+M(i,2)×N(2,j)+…+M(i,n)×N(n,j) 这就是说,为求Q的值,只有M(i,k)与N(k,j)(即M元素 的列与N元素的行相等的两项)才有相乘的机会,且当两项都不为零时,乘积中的这一项才不为零。 即只找到M.data中的j值和N.data中的i值相等的各对元素相乘即可。

  26. 2、相乘的基本操作是:对于M中每个元素 M.data[p],找到N中所有满足条件 M.data[p].j=N.data[q].i的 元素N.data[q], 求得M.data[p].e和M.data[q].e的乘积。 即M11只有可能和N中第1行的非零元素相乘,M12只有可能和N中第2行的非零元素相乘,…,而同一行的非零元是相邻存放的,所以求Q11和Q12同时进行,当然只有Mik和Nkj(列号与行号相等)且均不为零(三元组存在)时才相乘,并且累加到Qij当中去。

  27. 为了便于N.data中寻找N中的第row行第一个非零元素,与前面类似,在此需引入num和rpos两个向量。num[row]表示矩阵N中第row行的非零元素的个数;rpos[row]表示第row行的第一个非零元素在N.data中的位置。于是有为了便于N.data中寻找N中的第row行第一个非零元素,与前面类似,在此需引入num和rpos两个向量。num[row]表示矩阵N中第row行的非零元素的个数;rpos[row]表示第row行的第一个非零元素在N.data中的位置。于是有 rpos[1]=1 rpos[row]=rpos[row-1]+num[row-1] 2≤row≤n 例如 ,对于矩阵N的num和rpos如图所示。 row 1 2 3 4 num[row] 1 1 2 0 rpos[row] 1 2 3 5 图5.17 矩阵N的num与rpos值

  28. 3、根据以上分析,稀疏矩阵的乘法运算的粗略步骤如下:3、根据以上分析,稀疏矩阵的乘法运算的粗略步骤如下: ⑴初始化。清理一些单元,准备按行顺序存放乘积矩阵; ⑵求N的num,rpos; ⑶做矩阵乘法。将M.data中三元组的列值与N.data中三元组的行值相等的非零元素相乘,并将具有相同下标的乘积元素相加。 两个稀疏矩阵相乘(Q= M* N)的过程可大致描述如下: Q初始化; if (Q是非零矩阵) { // 逐行求积 for (arow=1; arow<=M.mu; ++arow) { // 处理M的每一行 ctemp[] = 0; // 累加器清零 计算Q中第arow行的积并存入ctemp[] 中; 将ctemp[] 中非零元压缩存储到Q.data; } // for arow } // if

  29. 算法描述: Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) { //求矩阵乘积Q=M* N,采用行逻辑链接存储。设M.nu=N.mu if (M.nu != N.mu) return ERROR; if (M.tu*N.tu != 0) { // Q是非零矩阵 {Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; p=1 // Q初始化 do { crow=M.data[p].i; //crow指示当前处理的行号 ctemp[] = 0; // 当前行各元素累加器清零 while (p<=M.tu && M.data[p].i==crow) { brow=M.data[p].j; //找到对应元在N中的行号 for (q=N.rpos[brow]; q<rpos[brow+1]; ++q) {ccol = N.data[q].j; // 乘积元素在Q中列号 ctemp[ccol] += M.data[p].e * N.data[q].e; } // for q ++p; }//求得Q中第crow行的非零元

  30. for (ccol=1; ccol<=Q.nu; ++ccol) // 压缩存储该行非零元 if (ctemp[ccol]) { ++Q.tu; Q.data[Q.tu] = (crow, ccol, ctemp[ccol]); } // if } // do while (p<=M.tu); } // if return OK; } // MultSMatrix

  31. 0 2 1 0 -2 4 0 0 • 0 0 5 • 0 -1 0 0 • 2 0 0 0 M= N= Q= 0 6 -1 0 0 4 当M和N是稀疏矩阵并用三元组表存储结构时,假设M和N分别为: 则Q=M*N为: 它们的三元组、积分别为: i j e i j e i j e 1 1 3 1 2 2 1 2 6 1 4 5 2 1 1 2 1 -1 2 2 -1 3 1 -2 3 2 4 3 1 2 3 2 4 m.data n.data q.data • 算法分析:T(n)=O(mp)

  32. col 3 2 1 val 4 5 8 row 4 2 2 down right 1 3 1 当矩阵的非零元个数和位置在操作过程中变化较大时 • 十字链表 • 设行指针数组和列指针数组,分别指向每行、列第一个非零元 • 结点定义 typedef struct node { int row,col,val; struct node *down, *right; }JD; ^ ^ ^ ^ ^ ^ ^

  33. 算法思想:从键盘接收信息建立十字链表算法 1、初始化头指针向量 2、初始化各行列链表 3、动态生成结点,输入非零元 4、将结点插入行 5、将结点插入列

  34. 1 2 3 1 8 5 4 7 4 2 2 2 ^ ^ 1 3 1 ^ ^ ^ ^ ^ ^ ^ ^ m=4,n=3 1,1,3 2,2,5 2,3,4 4,1,8 2,1,7

  35. 算法描述: Status CreateSMatrix_OL(CrossList &M) { //创建稀疏矩阵M。采用十字链表存储表示 if (M) free(M); scanf(&m,&n,&t); //输入M的行数、列数和非零元个数 M.mu=m; M.nu=n; M.tu=t; if (!(M.rhead=(Olink *) malloc ((m+1)*sizeof(Olink)))) exit (overflow); if (!(M.chead=(Olink *) malloc ((n+1)*sizeof(Olink)))) exit (overflow); M.rhead[ ]=M.chead[ ]=NULL;//初始化行列头指针向量; //各行列链表为空链表 for (scanf(&i,&j,&e); i!=0;scanf(&i,&j,&e)) { //按任意次序输入非零元 if (!(p=(OLNode *) malloc (sizeof(OLNode)))) exit (overflow); p->I=I; p->j=j; p->e=e; //生成结点

  36. 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; } //完成列插入 Return OK; }//CreateSMatrix_OL • 算法分析:此算法对非零元输入的先后次序没任何要求 T(n)=o(ts) 其中:t——非零元个数 s= max(m,n)

  37. 3 0 0 5 0 –1 0 0 2 0 0 0 3 0 4 5 0 6 0 0 0 0 8 0 0 0 4 5 0 7 0 0 -2 0 8 0 • 两个稀疏矩阵相加 • 算法思路: 假设非空指针pa和pb分别指向矩阵A和B中行值相同的两个结点: 则主要处理过程为: 1、若pa==NULL或pa->j>pb->j,则需要在A矩阵的链表中插入一个值为bij的结点。此时,需改变同一行中前一结点的right域值,以及同一列中前一结点的down域值。 2、若pa->j<pb->j,则只要将pa指针往右推进一步。 3、若pa->j==pb->j且pa->e+pb->e!=0,则只要将aij+bij的值送到pa所指结点的e域即可,其他所有域的值都不变。 4、若pa->j==pb->j且pa->e+pb->e==0,则需要在A矩阵的链表中删除pa所指的结点。此时,需改变同一行中前一结点的right域值,以及同一列中前一结点的down域值。 = +

  38. 5.3 矩阵的压缩存储 • 小 结 • 1 矩阵压缩存储是指为多个值相同的元素分配一个 • 存储空间,对零元素不分配存储空间; • 2 特殊矩阵的压缩存储是根据元素的分布规律,确定 • 元素的存储位置与元素在矩阵中的位置的对应关系; • 3 稀疏矩阵的压缩存储除了要保存非零元素的值外,还 • 要保存非零元素在矩阵中的位置;

  39. 5.4 广义表 • 广义表的概念 广义表也称为列表,是线性表的一种扩展,也是数据元素的有限序列。 记作:LS= (d0, d1, d2, . . . . . .dn-1)。其中di既可以是单个元素,也可以是广义表。 • 说明 • 广义表的定义是一个递归定义,因为在描述广义 表时又用到了广义表; • 在线性表中数据元素是单个元素,而在广义表中, 元素可以是单个元素, 称为单元素(原子),也可以是广义表,称为广义表的子表; • n 是广义表长度;

  40. A = ( )空表,表长为0;B = (a,(b,c,d))B的表长为2,两个元素分别为 a 和子表(b,c,d);C = (e)C中只有一个元素e,表长为1;D = (A,B,C,f ) D的表长为4,它的前三个元素 A,B,C广义表,第四个f 是单元素;E=( a ,E )递归表. • 下面是一些广义表的例子; • 若广义表不空,则可分成表头和表尾,反之,一对表头和表尾可唯一确定广义表

  41. 表头:称第一个元素为L的表头; • 表尾:其余元素组成的表称为LS的表尾; B = (a,(b,c,d)) 表头:a 表尾 ((b,c,d)) 即 HEAD(B)=a, TAIL(B)=((b,c,d)), C = (e) 表头:e 表尾 ( ) D = (A,B,C,f ) 表头:A 表尾 (B,C,f ) 运算可以嵌套,如: HEAD(TAIL(B))=b, TAIL(TAIL(B))=(c, d) 。 由表头、表尾定义可知:任何一个非空列表其表头可能是原子,也可能是列表,而其表尾必定为列表。

  42. D A B C f a D e b c d 广义表的元素之间除了存在次序关系外,还存在层次关系。如:

  43. 广义表的存储结构 由于广义表中数据元素可以具有不同结构,故难以用顺序结构表示广义表。通常采用链表存储方式 如何设定链表结点?广义表中的数据元素可能为单元素(原子)或子表,由此需要两种结点:一种是表结点,用以表示广义表;一种是单元素结点,用以表示单元素(原子)。 原子结点 表结点

  44. 广义表链表结点的类型定义 Typedef struct GLNode { int tag; 域:用于区分原子结点和表结点 union { int atom; //原子结点的值域 struct GLNode *hp; //表结点的表头指针域, }; struct GLNode *tp; //指向下一个元素的指针 }*GList;

  45. A ∧ B B 1 1 ∧ ∧ 1 1 ∧ ∧ ∧ C ∧ ∧ 1 1 0 0 0 0 ∧ ∧ ∧ ∧ 0 0 0 a a e 0 0 b b 0 c 0 c d d D D ∧ ∧ 1 1 1 1 E ∧ ∧ 1 1 1 1 f f ∧ 1 1 ∧ 0 a • 广义表的存储结构示例 A =(), B =(a,(b,c,d)) C = (e), D = (A,B,C, f ) E = (a, E)

  46. 广义表的基本操作的递归算法 广义表是递归结构,所以广义表的许多操作可以用递归算法实现, • 求广义表的深度 广义表 L= (α1, α2。。。αn) 的深度=广义表中括号重数 例 A=()B = (e) C = (a,(b,c,d)) D = (A,B,C) depth(A)=1 depth(B)=1 depth(C)=2 depth(D)=3 广义表的深度=1+MAX(depth(αi ))

  47. 1 1 depth(αi )的递归定义: 基本项:L 为空表,depth(αi )=1 L 为原子结点指针, depth(αi )=0 递归项:αi为非空表, depth(L )= 1+MAX(depth (αi )) L 0 a L = (a,(b,c,d)) 0 b c d 0 0

  48. 求广义表L的深度。int depth (NODE *head) { NODE *p; int max, deth1; p=head;max=0;//空表深度为1while (p!=NULL) { if(p->tag= =0) depth1=0; //原子深度为0 else depth1=depth(p->content.child); //求以p->content.child if(depth1>max)max=depth1; //为头指针的子表深度p=p->next; }return(max+1);//非空表的深度是各元素的深度的最大值加1 }

  49. 建立广义表 NODE *create( ) { NODE *p; char ch; ch=str[i];i++; switch(ch) { case '(': p=(NODE *)malloc(sizeof(NODE));p->tag=1; p->content.child=create( ); p->next=create( );break;

  50. case 'a': case 'b': case 'c': case 'd':case 'e': p=(NODE *)malloc(sizeof(NODE));p->tag=0; p->content.val=ch; p->next=create();break; case ',': p=create();break; case ')': case '\0': p=NULL; } return(p); }

More Related