数据结构实验广义表

合集下载

数据结构第5章 串和广义表

数据结构第5章 串和广义表

5.1 串的定义和基本运算
• (4)串的连接StrCat(S,T)。 • 初始条件:串S和T存在。 • 操作结果:将串T的值连接在串S的后面。 • (5)求子串SubString(Sub,S,pos,len)。 • 初始条件:串S存在,1≤pos≤StrLength(S)且
1≤len≤StrLength(S)-pos+1。 • 操作结果:用Sub返回串S的第pos个字符起长度为len的
1≤len≤StrLength(S)-pos+1。 • 操作结果:从串S中删除第pos个字符起长度为len的子串。 • (9)串的替换StrReplace(S,T,V)。 • 初始条件:串S,T和V存在,且T是非空串。 • 操作结果:用V替换串S中出现的所有与T相等的不重叠子
串。 • (10)判断串空StrEmpty(S)。 • 初始条件:串S存在。 • 操作结果:若串S为空串,则返回1;否则返回0。
• (1)非紧凑存储。设串S="Hello boy",计算机字长为32 位(4个Byte),用非紧凑格式一个地址只能存一个字符, 如图5-2所示。其优点是运算处理简单,但缺点是存储空 间十分浪费。
• (2)紧凑存储。同样存储S="Hello boy",用紧凑格式一 个地址能存四个字符,如图5-3所示。紧凑存储的优点是 空间利用率高,缺点是对串中字符处理的效率低。
•}
5.3 串的基本运算的实现
• (3)求子串操作。求串S从第pos位置开始,长度为len的 子串,并将其存入到串Sub中。操作成功返回1,不成功 返回0。其算法描述如下:
• int SubString(String *S,String *Sub,int pos,int len)

数据结构——用C语言描述(第3版)教学课件第5章 数组与广义表

数据结构——用C语言描述(第3版)教学课件第5章 数组与广义表
第5章 数组和广义表
5.1 数组的定义和运算 5.2 数组的顺序存储和实现 5.3 特殊矩阵的压缩存储
5.3.1 三角矩阵 5.3.2 带状矩阵 5.3.3 稀疏矩阵 5.4 广义表 5.5 总结与提高
5.1 数组的定义和运算
数组是一种数据类型。从逻辑结构上看,数组可以 看成是一般线性表的扩充。二维数组可以看成是线 性表的线性表。例如:
Am×n=
a12 a12 ┅
a1j
┅ a1n
a21 a22 ┅
a2j
┅ a2n
┇┇
ai1 ai2 ┅
aij
┇┇
┅ ain
am1 am2 ┅
amj
┅ amn
矩阵Am×n看成n个列向量的线性表,即j=(a1j,a2j, …,amj)
我们还可以将数组Am×n看成另外一个线性表: B=(1,,2,,… ,m),其中i(1≤i ≤m)本身也是一个线性表, 称为行向量,即: I= (ai1,ai2, …,aij ,…,ain)。
Loc[j1,j2,j3]=Loc[c1,c2,c3]+ α1*(j1-c1)+ α2*(j2-c2)+ α3(j3-c3)
=Loc[c1,c2,c3]+ Σαi*(ji-ci) (1≤i≤3)
由公式可知Loc[j1,j2,j3]与j1,j2,j3呈线性关系。 对于n维数组A(c1:d1,c2:d2,…,cn,dn),我们只要把上式推 广,就可以容易地得到n维数组中任意元素aj1j2…jn的存储 地址的计算公式。
疏矩阵。
0 12 9 0 0 0 0
0 0 3 0 0 15
0 0 0 00 0 0
12 0 0 0 18 0
M6×7= -3 0 0 0 0 14 0

数据结构第五章 数组与广义表

数据结构第五章 数组与广义表
an-1,n-1
压缩存储方法:只需要存储下三角 (含对角线)上的元素。可节省一 半空间。
可以使用一维数组Sa[n(n+1)/2]作为n阶对称矩阵A的存 储结构,且约定以行序为主序存储各个元素,则在Sa[k]和矩
阵元素aij之间存在一一对应关系: (下标变换公式)
i(i+1)/2 + j 当i≥j k = j(j+1)/2 + i 当i<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]; }
分析算法FastTransposeSMatrix的时间 复杂度:
for (col=1; col<=M.nu; ++col) … … for (t=1; t<=M.tu; ++t) … … for (col=2; col<=M.nu; ++col) … … for (p=1; p<=M.tu; ++p) … …
//对当前行中每一个非零元

brow=M.data[p].j;

if (brow < N.nu ) t = N.rpos[brow+1];
M
else { t = N.tu+1 }

for (q=N.rpos[brow]; q< t; ++q) { ccol = N.data[q].j; // 乘积元素在Q中列号
一、三元组顺序表
对于稀疏矩阵,非零元可以用三元组表示, 整个稀疏矩阵可以表示为所有非零元的三元组所 构成的线性表。例如:

数据结构递归与广义表

数据结构递归与广义表

第5章递归与广义表一、复习要点本章主要讨论递归过程和广义表。

一个递归的定义可以用递归的过程计算,一个递归的数据结构可以用递归的过程实现它的各种操作,一个递归问题也可以用递归的过程求解。

因此,递归算法的设计是必须掌握的基本功。

递归算法的一般形式:void p ( 参数表) {if( 递归结束条件)可直接求解步骤;基本项else p( 较小的参数);归纳项}在设计递归算法时,可以先考虑在什么条件下可以直接求解。

如果可以直接求解,考虑求解的步骤,设计基本项;如果不能直接求解,考虑是否可以把问题规模缩小求解,设计归纳项,从而给出递归求解的算法。

必须通过多个递归过程的事例,理解递归。

但需要说明的是,递归过程在时间方面是低效的。

广义表是一种表,它的特点是允许表中套表。

因此,它不一定是线性结构。

它可以是复杂的非线性结构,甚至允许递归。

可以用多重链表定义广义表。

在讨论广义表时,特别注意递归在广义表操作实现中的应用。

本章复习的要点:1、基本知识点要求理解递归的概念:什么是递归?递归的定义、递归的数据结构、递归问题以及递归问题的递归求解方法。

理解递归过程的机制与利用递归工作栈实现递归的方法。

通过迷宫问题,理解递归解法,从而掌握利用栈如何实现递归问题的非递归解法。

在广义表方面,要求理解广义表的概念,广义表的几个性质,用图表示广义表的方法,广义表操作的使用,广义表存储结构的实现,广义表的访问算法,以及广义表的递归算法。

2、算法设计求解汉诺塔问题,掌握分治法的解题思路。

求解迷宫问题、八皇后问题,掌握回溯法的解题思路。

对比单链表的递归解法和非递归解法,掌握单向递归问题的迭代解法。

计算广义表结点个数,广义表深度,广义表长度的递归算法。

输出广义表各个原子所在深度的非递归算法。

判断两个广义表相等的递归算法。

广义表的按深度方向遍历和按层次(广度)方向遍历的递归算法。

使用栈的广义表的按深度方向遍历的非递归算法。

递归的广义表的删除算法二、难点与重点1、递归:递归的定义、递归的数据结构、递归问题用递归过程求解链表是递归的数据结构,可用递归过程求解有关链表的问题2、递归实现时栈的应用递归的分层(树形)表示:递归树递归深度(递归树的深度)与递归工作栈的关系单向递归与尾递归的迭代实现3、广义表:广义表定义、长度、深度、表头、表尾用图形表示广义表的存储结构广义表的递归算法,包括复制、求深度、求长度、删除等算法三、教材中习题的解析5-1 已知A[n]为整数数组,试写出实现下列运算的递归算法:(1) 求数组A中的最大整数。

数据结构-广义线性表广义表

数据结构-广义线性表广义表
template <class T> class Lists { public: Lists( ) ; Lists(Lists ls1, Lists ls2); ~Lists( ); int Length( ); int Depth(GLNode<T> *ls); GLNode *Head( ); GLNode *Tail( ); private: GLNode<T> *ls; };
清华大学出版社
数据结构( 数据结构(C++版) 版
广义线性表——广义表 广义线性表——广义表 ——
广义表的示例 AБайду номын сангаас=( ) B =(e) C =(a, (b,c,d)) , , D =(A, B, C) E =(a, E) F =(( ))
长度?深度?表头?表尾? 长度?深度?表头?表尾?
清华大学出版社
数据结构( 数据结构(C++版) 版
广 义 表 类 的 声 明
清华大学出版社
广义线性表——广义表 广义线性表——广义表 ——
数据结构( 数据结构(C++版) 版
广义表的操作——建立广义表 建立广义表 广义表的操作 template <class T> Lists::Lists(Lists ls1,Lists ls2) { ls = new GLNode ls->tag = 1; ls->ptr.hp = ls1; ls->ptr.tp = ls2; }

C
1 0 a
1 1 0 b
1 0 c
1

0 d
清华大学出版社
广义线性表——广义表 广义线性表——广义表 ——

《数据结构与算法》第五章-数组和广义表学习指导材料

《数据结构与算法》第五章-数组和广义表学习指导材料

《数据结构与算法》第五章数组和广义表本章介绍的数组与广义表可视为线性表的推广,其特点是数据元素仍然是一个表。

本章讨论多维数组的逻辑结构和存储结构、特殊矩阵、矩阵的压缩存储、广义表的逻辑结构和存储结构等。

5.1 多维数组5.1.1 数组的逻辑结构数组是我们很熟悉的一种数据结构,它可以看作线性表的推广。

数组作为一种数据结构其特点是结构中的元素本身可以是具有某种结构的数据,但属于同一数据类型,比如:一维数组可以看作一个线性表,二维数组可以看作“数据元素是一维数组”的一维数组,三维数组可以看作“数据元素是二维数组”的一维数组,依此类推。

图5.1是一个m行n列的二维数组。

5.1.2 数组的内存映象现在来讨论数组在计算机中的存储表示。

通常,数组在内存被映象为向量,即用向量作为数组的一种存储结构,这是因为内存的地址空间是一维的,数组的行列固定后,通过一个映象函数,则可根据数组元素的下标得到它的存储地址。

对于一维数组按下标顺序分配即可。

对多维数组分配时,要把它的元素映象存储在一维存储器中,一般有两种存储方式:一是以行为主序(或先行后列)的顺序存放,如BASIC、PASCAL、COBOL、C等程序设计语言中用的是以行为主的顺序分配,即一行分配完了接着分配下一行。

另一种是以列为主序(先列后行)的顺序存放,如FORTRAN语言中,用的是以列为主序的分配顺序,即一列一列地分配。

以行为主序的分配规律是:最右边的下标先变化,即最右下标从小到大,循环一遍后,右边第二个下标再变,…,从右向左,最后是左下标。

以列为主序分配的规律恰好相反:最左边的下标先变化,即最左下标从小到大,循环一遍后,左边第二个下标再变,…,从左向右,最后是右下标。

例如一个2×3二维数组,逻辑结构可以用图5.2表示。

以行为主序的内存映象如图5.3(a)所示。

分配顺序为:a11 ,a12 ,a13 ,a21 ,a22,a23 ; 以列为主序的分配顺序为:a11 ,a21 ,a12 ,a22,a13 ,a23 ; 它的内存映象如图5.3(b)所示。

数据结构广义表

数据结构广义表

结点结构是无论什么结点都有三个域:
第一个域是结点类型标志tag; 第二个域是指向一个列表的指针(当tag=1时) 或一个原子(当tag=0时); 第三个域是指向下一个结点的指针tp。
3 广义表的存储结构
形式描述为:
typedef enum{ ATOM, LIST }ElemTag typedef struct GLNode { //定义广义表结点 ElemTage tag; //公共部分,用以区分 原子结点和表结点 Unin{ //原子结点和表结点的联合部分 AtomType atom;//原子类型结点域, // AtomType由用户定义 struct GLNode *hp,; //表结点的表头指针域 }; struct GLNode *tp; //指向下一个结点的指针 }*Glist; //广义表类型
5. E=(a,E)
这是一个递归列表,其元素中有自己。
广义表也可以用图形表示,例如前述的广义表D和E可表示为:
广义表D
D
广义表E
E
C
A
B
a
e
a b c d
2 广义表的基本运算
广义表的基本运算 ⑴ 取表头 HEAD(LS); ⑵ 取表尾 TAIL(LS)。
3 广义表的存储结构
广义表中的数据元素可以是单元素,或是广义表, •很难用顺序存储结构表示,常采用链式存储结构。 1.表头表尾链存储结构 有两类结点:表结点和单元素结点。
P 1 3 1 1
A=y((c,3),(D,2)) C=x((1,10),(2,6))

1 2
A
z y 1 1 1 3
C
x 0 0 15 ^
B
1 2
1 2

广义表实验报告

广义表实验报告

广义表实验报告一、实验目的广义表是一种非线性的数据结构,本次实验的主要目的是深入理解广义表的概念、存储结构和基本操作,并通过编程实现对广义表的各种操作,以提高对数据结构的理解和编程能力。

二、实验环境本次实验使用的编程语言是C++,编译环境为Visual Studio 2019。

三、广义表的概念广义表是线性表的推广,它允许表中的元素本身也是一个广义表。

广义表通常用一对圆括号“()”来表示,元素之间用逗号“,”分隔。

例如,(a, (b, c), d) 就是一个广义表,其中 a、d 是原子元素,(b, c) 是子表。

广义表可以分为表头和表尾两部分。

表头是广义表的第一个元素,表尾是除表头外的其余元素组成的广义表。

例如,对于广义表(a, (b,c), d),表头是 a,表尾是((b, c), d)。

四、广义表的存储结构1、头尾链表存储结构每个节点包含一个标志位 tag,用于区分原子节点和子表节点。

当 tag = 0 时,为原子节点,包含一个数据域 atom 和一个指向下一个节点的指针 next。

当 tag = 1 时,为子表节点,包含一个指向表头节点的指针 hp 和一个指向表尾节点的指针 tp。

2、扩展线性链表存储结构每个节点包含一个标志位 tag、一个数据域 data 和两个指针域 hp和 tp。

当 tag = 0 时,data 存储原子元素的值,hp 和 tp 均为 NULL。

当 tag = 1 时,data 为 NULL,hp 指向表头节点,tp 指向表尾节点。

五、广义表的基本操作1、创建广义表输入广义表的字符串表示,通过递归算法构建广义表的存储结构。

2、输出广义表以递归的方式遍历广义表的存储结构,输出广义表的字符串表示。

3、求广义表的深度递归地计算每个子表的深度,广义表的深度为所有子表深度的最大值加 1。

4、求广义表的长度遍历广义表的存储结构,统计原子节点和子表节点的个数。

5、复制广义表递归地复制广义表的每个节点,创建一个新的广义表存储结构。

数据结构广义表

数据结构广义表

{ printf("("); /*输出'('*/
if (g->val.sublist==NULL) printf(""); /*输出空子表*/
else DispGL(g->val.sublist); /*递归输出子表*/
}
else printf("%c", g->val.data); /*为原子时输出元素值*/
假如把每个表旳名字(若有旳话)写在其表旳前面,则 上面旳5个广义表可相应地体现如下:
A()
B(e)
C(a,(b,c,d))
D(A(),B(e),C(a,(b,c,d)))
E((a,(a,b),((a,b),c)))
若用圆圈和方框分别体现表和单元素,并用线段把表 和它旳元素(元素结点应在其表结点旳下方)连接起来,则 可得到一种广义表旳图形体现。例如,上面五个广义表 旳图形体现如下图所示。
A() B(e) C(a,(b,c,d)) D(A(),B(e),C(a,(b,c,d))) E((a,(a,b),((a,b),c)))
AB e
C A
a b cd
D BC
ea b cd
E
a
ab
c
ab
8.2 广义表旳存储构造
广义表是一种递归旳数据构造,所以极 难为每个广义表分配固定大小旳存储空间,所
GLNode *CreatGL(char *&s)
{ GLNode *h;char ch=*s++; /*取一种扫描字符*/
if (ch!='\0')
/*串未结束判断*/
{ h=(GLNode *)malloc(sizeof(GLNode));/*创建新结点*/

数据结构-串、数组和广义表-实验

数据结构-串、数组和广义表-实验

数据结构-串、数组和⼴义表-实验实验四串、数组和⼴义表⼀、⽬的和要求1. 掌握串、数组和⼴义表的逻辑结构定义和各种存储结构的实现。

2. 熟练运⽤串、数组和⼴义表的的各种存储结构以及各种基本操作。

3. 根据实际问题的需要,选择串、数组和⼴义表适合的存储结构解决问题。

⼆、实验环境1.WindowsXP操作系统;2.DEV C++、Visual C++6.0语⾔环境;三、实验内容(⼀)验证性实验(第1、3题⼀组;第2、4题为另⼀组,每个同学选择⼀组完成。

每个⼩题⼀个⽂件夹,所有⽂件夹打在⼀个包中,⽂件名:“学号”+“姓名”,例如: 13131000张三.rar 。

提交码为2014DS4,截⽌时间:2014年12⽉30⽇12:00时。

)1.KMP算法的验证(1)设计测试⽤例,对教材介绍的模式匹配算法进⾏验证,把运⾏结果截屏保存。

(2)修改KMP算法中求失效值的函数,解决原算法中的⽆效匹配问题,提⾼匹配效率。

2.三元组顺序表的验证(1)设计测试⽤例,对三元组顺序表进⾏验证,把运⾏结果截屏保存。

(2)重载加法运算符,实现两个矩阵的加法运算。

3.⼗字链表的验证(1)设计测试⽤例,对⼗字链表进⾏验证,把运⾏结果截屏保存。

(2)增加成员函数Transpose(),实现矩阵的转置运算。

4.⼴义链表的验证(1)设计测试⽤例,对⼴义链表进⾏验证,把运⾏结果截屏保存。

(2)增加成员函数reversal(),实现⼴义表的转置运算。

(⼆)设计性实验(⼩组完成)5.串的链式存储参照教材中串的顺序存储的类String,设计并实现串的链式存储的类LinkString(简称链串)。

在链串中字符串的信息存储在⼀个带头结点的单链表中。

如图1所⽰是字符串“ABCDEF”的链式存储结构⽰意图。

基本要求:完成链串的定义(函数成员与顺序存储的类String类似)和实现,并完成串的相关函数在串类上的实现。

选做内容:为了提⾼存储密度,考虑在链表的⼀个结点中存放多个字符(例如,放4个字符)。

数据结构实验报告_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的三元组。

算法与数据结构实验报告——树及其应用

算法与数据结构实验报告——树及其应用

北京邮电大学软件学院2019-2020学年第1学期实验报告课程名称:算法与数据结构课程设计实验名称:树及其应用实验完成人:日期: 2019 年 11月 10 日一、实验目的树是一种应用极为广泛的数据结构,也是这门课程的重点。

它们的特点在于非线性。

广义表本质上是树结构。

本章实验继续突出了数据结构加操作的程序设计观点,但根据这两种结构的非线性特点,将操作进一步集中在遍历操作上,因为遍历操作是其他众多操作的基础。

遍历逻辑的(或符号形式的)结构,访问动作可是任何操作。

本次实验希望帮助学生熟悉各种存储结构的特征,以及如何应用树结构解决具体问题(即原理与应用的结合)。

二、实验内容必做内容1)二叉树的建立与遍历[问题描述]建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。

[基本要求]从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序),将遍历结果打印输出。

[测试数据]ABCффDEфGффFффф(其中ф表示空格字符)则输出结果为先序:ABCDEGF中序:CBEGDFA后序:CGBFDBA2)打印二叉树结构[问题描述]按凹入表形式横向打印二叉树结构,即二叉树的根在屏幕的最左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。

例如:[测试数据]由学生依据软件工程的测试技术自己确定。

注意测试边界数据,如空二叉树。

[实现提示](1)利用RDL遍历方法;(2)利用结点的深度控制横向位置。

选做内容采用非递归算法实现二叉树遍历。

三、实验环境Windows下利用vs 2019完成,语言c++四、实验过程描述首先构造Tree类,内含树的结构体BiTree,以及本实验所要用到的一些操作typedef struct BiTNode{TElemType data;int degree, depth, level; //度,高度,高度差struct BiTNode* lchild, * rchild; /* 左右孩子指针 */}BiTNode, * BiTree;实现相应功能:1、二叉树的建立与遍历构造二叉树:前序构造,先赋值,然后递归构造左子树,递归构造右函数BiTNode* Tree::CreatBiTree(BiTree T) {TElemType ch;cin >> noskipws >> ch; //不跳过空格if (ch == ' ')T = NULL; //输入空格表示空子树else {T = new BiTNode; //分配空间if(!T) //分配失败就退出throw new std::bad_alloc;T->degree = 0; //记录度(T)->data = ch;T->depth++; //度增加T->lchild=CreatBiTree(T->lchild); //递归创建左子树T->rchild=CreatBiTree(T->rchild); //递归创建右子树if (T->lchild != NULL)T->degree++; //有一个孩子度就加一if (T->rchild != NULL)T->degree++;}return T;}销毁二叉树:后序递归销毁左右子树(需要先查找到子树,销毁再销毁父亲树)void Tree::Release(BiTree T) {if (T != NULL) {Release(T->lchild); //递归销毁左子树Release(T->rchild); //递归销毁右子树delete T;}}//前序遍历void Tree::PreOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) { if (T) /* T不空 */{(this->*Visit)(T); /* 先访问根结点 */PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */ }}//中序遍历void Tree::InOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */ }}//后序遍历void Tree::PostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){PostOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */PostOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */(this->*Visit)(T); /* 再访问根结点 */}}//查找深度int Tree::TreeDepth(BiTree T) {int i, j;if (!T)return 0; /* 空树深度为0 */if (T->lchild)i = TreeDepth(T->lchild); /* i为左子树的深度 */elsei = 0;if (T->rchild)j = TreeDepth(T->rchild); /* j为右子树的深度 */elsej = 0;T->depth = i > j ? i + 1 : j + 1;return T->depth;}//得到层数void Tree::getLevel(BiTree T, int level){if (T){T->level = level;getLevel(T->lchild, level + 1); //得到左子树的层数,左子树根节点的层数比此节点多一getLevel(T->rchild, level + 1); //得到右子树的层数,右子树根节点的层数比此节点多一}}//非递归中序遍历void Tree::NoRecInOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {S.Push(p); //当节点不为空时就压栈,然后判断左孩子p = p->lchild;}else {p=S.Pop(); //返回到父节点(this->*Visit)(p); //访问p = p->rchild; //然后指向右节点}}}实验二:2、打印二叉树结构//中序遍历RDLvoid Tree::InOrderTraverseRDL(BiTree T, void(Tree::* Visit)(BiTree)) {if (T){InOrderTraverseRDL(T->rchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverseRDL(T->lchild, Visit); /* 最后中序遍历右子树 */ }}//打印二叉树图形打印图形时,需要中序遍历RDL(先遍历右节点,再遍历右节点)。

数据结构29:广义表的长度和深度

数据结构29:广义表的长度和深度

数据结构29:⼴义表的长度和深度⼴义表的长度通过前⼀节对⼴义表的介绍,例⼦中给出了⼏个⼴义表的长度。

例如:空表的长度为 0,只含有⼀个原⼦的⼴义表长度为 1,等等。

⼴义表的长度指的是⼴义表中数据元素的数量。

这⾥需要指明的是,⼀个⼴义表中,⼀个原⼦算做是⼀个元素,⼀个⼦表也只算做⼀个元素。

在 LS = (a1,a2,…,a n) 中,a i表⽰原⼦或者⼦表, LS 的长度为 n。

⼴义表的深度⼴义表的深度,指的是⼴义表中括号的重数。

例如:C=(a,(b,c,d)):图1 ⼴义表C的深度图1中,从前往后数左括号的数量就是⼴义表C的深度,为2;也可以从右往左数右括号的数量(红⾊)。

求解⼴义表的深度求⼴义表的深度之前,⾸先要将⼴义表⽤某个数据结构表⽰出来,在前边学习⼴义表时,介绍了两种表⽰⼴义表的⽅法。

这⾥采⽤的⽅法是第⼀种。

表⽰结构为:(拿⼴义表C为例)⼴义表第⼀节中有具体实现的代码,实现函数为:creatGlist(Glist C)。

这⾥不再过多介绍。

求⼴义表深度的算法⽤到的是递归的思想,解题思路是:1. 从⼴义表 C 的开头位置,⼀次遍历表中每个数据元素:当遍历对象为原⼦时,返回原⼦的深度为 0 ;遍历对象为表 C 的⼦表时,继续遍历⼦表中的数据元素。

2. 递归的出⼝有两个:当遍历对象为原⼦时,返回 0 ;遍历对象为空表时,返回 1 (空表的深度为 1 );3. 设置⼀个初始值为 0 的整形变量 max ,⽤ max 和遍历过程中返回的整形数值进⾏⽐较,取⼤的那⼀个,知道程序结束,max + 1就是⼴义表的深度。

实现代码为:int GlistDepth(Glist C){ //如果表C为空表时,直接返回长度1; if (!C) { return1; } //如果表C为原⼦时,直接返回0; if (C->tag == 0) { return0; } int max = 0; //设置表C的初始长度为0; for (Glist pp=C; pp; pp=pp->ptr.tp) { int dep = GlistDepth(pp->ptr.hp); if (dep>max) { max = dep; //每次找到表中遍历到深度最⼤的表,并⽤max记录 } } //程序运⾏⾄此处,表明⼴义表不是空表,由于原⼦返回的是0,⽽实际长度是1,所以,此处要+1; return max+1;}完整代码演⽰#include <stdio.h>#include <stdlib.h>typedef struct GLNode{ int tag; //标志域 union { char atom; //原⼦结点的值域 struct { struct GLNode *hp, *tp; }ptr; //⼦表结点的指针域,hp指向表头;tp指向表尾 };}*Glist, GNode;Glist creatGlist(Glist C){ //⼴义表C C=(Glist)malloc(sizeof(GNode)); C->tag = 1; //表头原⼦‘a’ C->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.hp->tag = 0; C->ptr.hp->atom = 'a'; //表尾⼦表(b,c,d),是⼀个整体 C->ptr.tp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->tag = 1; C->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.tp = NULL; //开始存放下⼀个数据元素(b,c,d),表头为‘b’,表尾为(c,d) C->ptr.tp->ptr.hp->tag = 1; C->ptr.tp->ptr.hp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.hp->atom = 'b'; C->ptr.tp->ptr.hp->ptr.tp = (Glist)malloc(sizeof(GNode)); //存放⼦表(c,d),表头为c,表尾为d C->ptr.tp->ptr.hp->ptr.tp->tag = 1; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->atom = 'c'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp = (Glist)malloc(sizeof(GNode)); //存放表尾d C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->tag = 1; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(GNode)); C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->tag = 0; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->atom = 'd'; C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.tp = NULL; return C;}//求⼴义表的深度,递归调⽤int GlistDepth(Glist C){ if (!C) { return1; } if (C->tag == 0) { return0; } int max = 0; for (Glist pp=C; pp; pp=pp->ptr.tp) { int dep = GlistDepth(pp->ptr.hp); if (dep>max) { max = dep; } } return max+1;}int main(int argc, const char *argv[]){ Glist C = creatGlist(C); printf("%d", GlistDepth(C)); return0;}运⾏结果:2。

数据结构实验总结报告

数据结构实验总结报告

数据结构实验总结报告数据结构实验总结报告⼀、调试过程中遇到哪些问题?(1)在⼆叉树的调试中,从⼴义表⽣成⼆叉树的模块花了较多时间调试。

由于⼀开始设计的⼴义表的字符串表⽰没有思考清晰,处理只有⼀个孩⼦的节点时发⽣了混乱。

调试之初不以为是设计的问题,从⽽在代码上花了不少时间调试。

⽬前的设计是:Tree = Identifier(Node,Node)Node = Identifier | () | TreeIdentifier = ASCII Character例⼦:a(b((),f),c(d,e))这样便消除了歧义,保证只有⼀个孩⼦的节点和叶节点的处理中不存在问题。

(2)Huffman树的调试花了较长时间。

Huffman编码本⾝并不难处理,⿇烦的是输⼊输出。

①Huffman编码后的⽂件是按位存储的,因此需要位运算。

②⽂件结尾要刷新缓冲区,这⾥容易引发边界错误。

在实际编程时,⾸先编写了屏幕输⼊输出(⽤0、1表⽰⼆进制位)的版本,然后再加⼊⼆进制⽂件的读写模块。

主要调试时间在后者。

⼆、要让演⽰版压缩程序具有实⽤性,哪些地⽅有待改进?(1)压缩⽂件的最后⼀字节问题。

压缩⽂件的最后⼀字节不⼀定对齐到字节边界,因此可能有⼏个多余的0,⽽这些多余的0可能恰好构成⼀个Huffman编码。

解码程序⽆法获知这个编码是否属于源⽂件的⼀部分。

因此有的⽂件解压后末尾可能出现⼀个多余的字节。

解决⽅案:①在压缩⽂件头部写⼊源⽂件的总长度(字节数)。

需要四个字节来存储这个信息(假定⽂件长度不超过4GB)。

②增加第257个字符(在⼀个字节的0~255之外)⽤于EOF。

对于较长的⽂件,会造成较⼤的损耗。

③在压缩⽂件头写⼊源⽂件的总长度%256的值,需要⼀个字节。

由于最后⼀个字节存在或不存在会影响⽂件总长%256的值,因此可以根据这个值判断整个压缩⽂件的最后⼀字节末尾的0是否在源⽂件中存在。

(2)压缩程序的效率问题。

在编写压缩解压程序时①编写了屏幕输⼊输出的版本②将输⼊输出语句⽤位运算封装成⼀次⼀个字节的⽂件输⼊输出版本③为提⾼输⼊输出效率,减少系统调⽤次数,增加了8KB的输⼊输出缓存窗⼝这样⼀来,每写⼀位⼆进制位,就要在内部进⾏两次函数调⽤。

数据结构数组和广义表

数据结构数组和广义表

数据结构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)数组地每个数据元素都与一组唯一地下标值对应。

数据结构讲义第5章-数组和广义表

数据结构讲义第5章-数组和广义表
对于一个矩阵结构,显然用一个二维数组来表示是非常 恰当的.但有时会遇到这样一类矩阵:在这种矩阵中有 许多值相同的元素或者是零元素,为了节省存储空间, 可以对这类矩阵进行压缩存储. 压缩存储是:为多个值相同的元素只分配一个存储空间: 对零元素不分配存储空间. 特殊矩阵:值相同的元素或者零元素在矩阵中的分布有 一定规律,则称此类矩阵为特殊矩阵,反之,称为稀疏 矩阵.
5.4 广义表
5)若广义表不空,则可分成表头和表尾,反之,一对表头和表尾 可唯一确定广义表 对非空广义表:称第一个元素为L的表头,其余元素组成的表称 为LS的表尾; B = (a,(b,c,d)) 表头:a 表尾 ((b,c,d)) 即 HEAD(B)=a, C = (e) D = (A,B,C,f ) 表头:e 表尾 ( ) TAIL(B)=((b,c,d)),
5.4 广义表
4)下面是一些广义表的例子; 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 广义表, 4 A,B,C , 第四个是单元素; E=( a ,E ) 递归表.
以二维数组为例:二维数组中的每个元素都受两个线性关 系的约束即行关系和列关系,在每个关系中,每个元素aij 都有且仅有一个直接前趋,都有且仅有一个直接后继. 在行关系中 aij直接前趋是 aij直接后继是 在列关系中 aij直接前趋是 aij直接后继是
a00 a01 a10 a11
a0 n-1 a1 n-1
a11 a21 ┇ a12 a22 ┇ ai2 ┇ … amj … amn … aij … ain … … a1j a2j … … a1n a2n β1 β2 ┇ βi ┇ βm

《数据结构》数组和广义表 (2)

《数据结构》数组和广义表  (2)
2
顺序存储方式:按低地址优先(或高地址优先)顺序存入一维 数组。 (难点是多维数组与一维数组的地址映射关系)
补充:
链式存储方式:用带行指针向量的单链表来表示。 行指针向量
a11
… …
a12

a1n ^
am1
^
am2

amn ^
注:数组的运算参见下一节实例(稀疏矩阵的转置)
3
5.3 矩阵的压缩存储
(( 1,2,12) ,(1,3,9), (3,1,-3), (3,5,14),
(4,3,24), (5,2,18) ,(6,1,15), (6,4,-7))
6
法2:用三元组矩阵表示:
i
j
value
0
6
6
8
1
1
2
12
2
1
3
9
3
3
1
-3
4
3
5
14
5
4
3
24
6
5
2
18
7
6
1
15
8
6
4
-7
0 12 9 0 0 0 0 0 0000 -3 0 0 0 14 0 0 0 24 0 0 0 0 18 0 0 0 0 15 0 0 -7 0 0
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 14 0 0 0 0 0 0 0 00
(1, 3, -3) (1, 6, 15) (2, 1, 12) (2, 5, 18) (3, 1, 9) (3, 4, 24) (4, 6, -7) (5, 3, 14)
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《数据结构》实验报告◎实验题目: 广义表的创建与遍历。

◎实验目的:熟悉和掌握广义表的定义及结构,可以创建及遍历广义表。

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

一、需求分析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);}}1.程序使用说明:(1)本程序的运行环境为VC6.0。

(2)进入演示程序后即显示提示信息:请输入广义表:输入数据该广义表为:输出广义表2.测试结果:输入((),((a,b),(c,d))) 输出((),((a,b),(c,d)))错误输入:如果输入((),((a,b),(c,d)))) 输出((),((a,b),(c,d)))3.运行界面:输入((),((a,b),(c,d))) 输出((),((a,b),(c,d)))错误输入:如果输入((),((a,b),(c,d)))) 输出((),((a,b),(c,d)))五、实验总结本次编程我首先思考了广义表建立的算法,,并借鉴了网上一些算法,完善了自己的算法,然后在纸上写了自己的程序主体,中间进栈遇到了一些问题,当时没有考虑到设定全局变量,导致无法进栈,后来编程课中在同学的帮助下解决了栈的问题,基本再没有遇到问题,程序完美运行,通过这次试验,我对于广义表的理解更加深了一层,更熟悉广义表及栈。

教师评语:实验成绩:#include<stdio.h>#include<malloc.h>#define maxsize 100//定义广义表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 *Push(Snode *top,node *input){Snode *s;s=(Snode *)malloc(sizeof(Snode)); /*申请新节点*/s->data=input;s->next=top;top=s;return(top);}// 出栈函数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);}}//广义表输入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);}//广义表输出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");}int main(){node *head;printf("请输入广义表:\n");head=create();printf("该广义表为:\n");print(head);getchar();getchar();return 0;}。

相关文档
最新文档