版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第六章 树和二叉树学时:学时:10 学时学时本章主要内容:本章主要内容:1 1、 树的定义和存储结构树的定义和存储结构2 2、 二叉树的定义、性质、存储结构二叉树的定义、性质、存储结构3 3、 二叉树的遍历、线索算法二叉树的遍历、线索算法4 4、 树和二叉树的转换树和二叉树的转换5 5、 哈夫曼树及其应用哈夫曼树及其应用本章重点难点:本章重点难点: 1 1、二叉树的遍历、二叉树的遍历 2 2、线索算法、线索算法 3 3、哈夫曼树及其应用、哈夫曼树及其应用第六章 树和二叉树6.1 6.1 树的基本概念树的基本概念6.2 6.2 二叉树二叉树6.3 6.3 遍历二叉树和线索二叉树遍历
2、二叉树和线索二叉树6.4 6.4 树和森林的表示方法树和森林的表示方法6.5 6.5 赫夫曼树及其应用赫夫曼树及其应用6.6 6.6 树的计数与树的恢复树的计数与树的恢复第六章 树和二叉树6.1 树的类型定义树的类型定义一、一、 树的定义树的定义 1 1树的定义树的定义 树树TreeTree是是n nn0n0个有限数据元素的集合。在个有限数据元素的集合。在任意一棵非空树任意一棵非空树T T中:中:(1有且仅有一个特定的称为树根有且仅有一个特定的称为树根Root的结点,根结点无前趋结点;的结点,根结点无前趋结点;(2当当n1时,除根结点之外的其余结点被时,除根结点之外的其余结点被分成分成mm0个
3、互不相交的集合个互不相交的集合T1,T2,Tm,其中每一个集合,其中每一个集合Ti1 i m本身又是本身又是一棵树,并且称为根的子树。一棵树,并且称为根的子树。 1 2 3 4ABCHGFEDJI2树的其它表示法树的其它表示法 (1嵌套集合法嵌套集合法 嵌套集合法,也称为文氏图法嵌套集合法,也称为文氏图法Venn Diagram),它是用集合以及集合的),它是用集合以及集合的包含关系来描述树形结构,每个圆圈表示一个集合,套起来的圆圈表示包含关系。包含关系来描述树形结构,每个圆圈表示一个集合,套起来的圆圈表示包含关系。 ABCEIJDFGH6.1 6.1 树的类型定义树的类型定义( 2 ) 圆括
4、号表示法圆括号表示法 圆括号表示法也称为广义表表示法,它是使用括号将集合层次与包含关系圆括号表示法也称为广义表表示法,它是使用括号将集合层次与包含关系显示出来。显示出来。 ( A ( B ( D, E ( I, J ), F ), C ( G, H ) ) ) ( 3 ) 凹入法 凹入法是用不同宽度的行来显示各结点,而行的凹入程度体现了各结点集合的包含关系,。 树的凹入表示法主要用于树的屏幕显示和打印输出。ABCEDJFGHI6.1 6.1 树的类型定义树的类型定义3 .基本术语基本术语(1结点结点树的结点包含一个数据及若干指向树的结点包含一个数据及若干指向其子树的分支。其子树的分支。(2结点
5、的度结点的度结点所拥有的子树数称为该结结点所拥有的子树数称为该结点的度点的度Degree)。)。(3树的度树的度树中各结点度的最大值称为该树树中各结点度的最大值称为该树的度。的度。(4叶子终端结点)叶子终端结点)度为零的结点称为叶度为零的结点称为叶子结点。子结点。(5分枝结点分枝结点度不为零的结点称为分支结点。度不为零的结点称为分支结点。(6兄弟结点兄弟结点同一父亲结点下的子结点称为同一父亲结点下的子结点称为兄弟结点。兄弟结点。(7层数层数树的根结点的层数为树的根结点的层数为1,其余结点,其余结点的层数等于它双亲结点的层数加的层数等于它双亲结点的层数加1。(8树的深度树的深度树中结点的最大层数
6、称为树的树中结点的最大层数称为树的深度或高度)。深度或高度)。(9有向树:有向树: 有确定的根;有确定的根; 树根和子树根之间为有向关系。树根和子树根之间为有向关系。6.1 树的类型定义树的类型定义(10森林森林零棵或有限棵互不相交的树的集合称为森林。零棵或有限棵互不相交的树的集合称为森林。 在数据结构中,树和森林并不象自然界里有一个明显的量的差别。任何一在数据结构中,树和森林并不象自然界里有一个明显的量的差别。任何一棵树,只要删去根结点就成了森林。棵树,只要删去根结点就成了森林。ABCHGFEDJIKJBCDEFGHIK(a) (a) 树树 (b) (b) 移去根结点后成为森林移去根结点后成
7、为森林(11有序树和无序树有序树和无序树树中结点的各子树从左到右是有次序的即不能互树中结点的各子树从左到右是有次序的即不能互换位置),称这样的树为有序树;否则称为无序树。换位置),称这样的树为有序树;否则称为无序树。6.1 树的类型定义树的类型定义4.树的抽象数据类型定义树的抽象数据类型定义ADT Tree数据对象数据对象D:数据关系数据关系R:基本操作基本操作 P: ADT TreeD是具有相同特性的数据元素的集合。是具有相同特性的数据元素的集合。若若D为空集,则称为空树;为空集,则称为空树;/允许允许n=0若若D中仅含一个数据元素,则中仅含一个数据元素,则R为空集;为空集;其他情况下的其他
8、情况下的R存在二元关系:存在二元关系: root 独一独一 /关于根的说明关于根的说明 DjDk= /关于子树不相交的说明关于子树不相交的说明 /关于数据元素的说明关于数据元素的说明 /至少有至少有15个,如求树深,求某结点的双亲个,如求树深,求某结点的双亲6.1 树的类型定义树的类型定义TreeEmpty(T) / 判定树是否为空树判定树是否为空树 TreeDepth(T) / 求树的深度求树的深度TraverseTree( T, Visit() ) / 遍历遍历InitTree(&T) / 初始化置空树初始化置空树 CreateTree(&T, definition) /
9、按定义构造树按定义构造树Assign(T, cur_e, value) / 给当前结点赋值给当前结点赋值InsertChild(&T, &p, i, c) / 将以将以c为根的树插入为结点为根的树插入为结点p的第的第i棵子树棵子树 ClearTree(&T) / 将树清空 DestroyTree(&T) / 销毁树的结构销毁树的结构DeleteChild(&T, &p, i) / 删除结点删除结点p的第的第i棵子树棵子树基本操作基本操作 P: Root(T) / 求树的根结点 Value(T, cur_e) / 求当前结点的元素值 Parent(
10、T, cur_e) / 求当前结点的双亲结点求当前结点的双亲结点LeftChild(T, cur_e) / 求当前结点的最左孩子求当前结点的最左孩子 RightSibling(T, cur_e) / 求当前结点的右兄弟求当前结点的右兄弟Value(T, cur_e) / 求当前结点的元素值求当前结点的元素值6.1 树的类型定义树的类型定义 5. 5. 树型结构与线性结构的结构特点比较树型结构与线性结构的结构特点比较线性结构线性结构 第一个数据元素第一个数据元素( (无前驱无前驱) ) 最后一个数据元素最后一个数据元素( (无后继无后继) ) 其它数据元素其它数据元素( (一个前驱、一个后继一个
11、前驱、一个后继) )树型结构树型结构 根结点根结点( (无前驱无前驱) ) 多个叶子结点多个叶子结点( (无后继无后继) ) 其它数据元素其它数据元素( (一个前驱、多个后继一个前驱、多个后继) )6.1 树的类型定义树的类型定义6.2 二叉树的类型定义二叉树的类型定义为何要重点研究每结点最多只有两个为何要重点研究每结点最多只有两个 “叉叉” 的树?的树?二叉树的结构最简单,规律性最强;二叉树的结构最简单,规律性最强;可以证明,所有树都能转为唯一对应的二叉树,不失一般性。可以证明,所有树都能转为唯一对应的二叉树,不失一般性。6.2.1 二叉树的定义二叉树的定义6.2.2 二叉树的性质二叉树的性
12、质6.2.3 二叉树的存储结构二叉树的存储结构1、定义: 二叉树或为空树,或是由一个根结点加上两棵分别称为左子树和右子树的、互不交的二叉树组成。ABCDEFGHK根结点左子树右子树6.2.1 二叉树的定义二叉树的定义逻辑结构:逻辑结构: 一对二一对二1:2) 基本特征基本特征: 每个结点最多只有两棵子树不存在度大于每个结点最多只有两棵子树不存在度大于2的结点);的结点); 左子树和右子树次序不能颠倒。左子树和右子树次序不能颠倒。6.2 二叉树的类型定义二叉树的类型定义基本形态:基本形态:6.2 二叉树的类型定义二叉树的类型定义一般的树一般的树有几种?有几种?2.二叉树的抽象数据类型定义ADT
13、BinaryTree数据对象数据对象D:数据关系数据关系R: 基本操作基本操作 P:ADT BinaryTreeD是具有相同特性的数据元素的集合。是具有相同特性的数据元素的集合。若若D=,则,则R= ;若若D,则,则R= H;存在二元关系:;存在二元关系: root 独一独一 /关于根的说明关于根的说明 DjDk= /关于子树不相交的说明关于子树不相交的说明 /关于数据元素的说明关于数据元素的说明 /关于左子树和右子树的说明关于左子树和右子树的说明 /至少有至少有20个,如返回某结点的左孩子,个,如返回某结点的左孩子,或中序遍历,等等或中序遍历,等等6.2 二叉树的类型定义二叉树的类型定义 R
14、oot(T); Value(T, e); Parent(T, e); LeftChild(T, e); RightChild(T, e); LeftSibling(T, e); RightSibling(T, e); BiTreeEmpty(T); BiTreeDepth(T); PreOrderTraverse(T, Visit(); InOrderTraverse(T, Visit(); PostOrderTraverse(T, Visit(); LevelOrderTraverse(T, Visit(); InitBiTree(&T); Assign(T, &e, val
15、ue); CreateBiTree(&T, definition); InsertChild(T, p, LR, c); ClearBiTree(&T); DestroyBiTree(&T); DeleteChild(T, p, LR); 基本操作基本操作 P:6.2 二叉树的类型定义二叉树的类型定义 性质性质 1 : 在二叉树的第在二叉树的第 i 层上至多有层上至多有2i-1 个结点。个结点。 (i1)用归纳法证明:用归纳法证明: 归纳基:归纳基: 归纳假设:归纳假设: 归纳证明:归纳证明:i = 1 层时,只有一个根结点:层时,只有一个根结点: 2i-1 = 20
16、= 1;假设对所有的假设对所有的 j,1 j i,命题成立;,命题成立;二叉树上每个结点至多有两棵子树,二叉树上每个结点至多有两棵子树,则第则第 i 层的结点数层的结点数 = 2i-2 2 = 2i-1 。6.2.2二叉树的性质二叉树的性质 (3+2)6.2 二叉树的类型定义二叉树的类型定义 性质性质 2 : 深度为深度为 k 的二叉树上至多含的二叉树上至多含 2k-1 个结点个结点k1)。)。证明:证明: 基于上一条性质,深度为 k 的二叉树上的结点数至多为 20+21+ +2k-1 = 2k-1 。 性质性质 3 : 对任何一棵二叉树,若它含有对任何一棵二叉树,若它含有n0 个叶子结点、个
17、叶子结点、n2 个度个度为为 2 的结点,则必存在关系式:的结点,则必存在关系式:n0 = n2+1。证明:证明:设设 二叉树上结点总数二叉树上结点总数 n = n0 + n1 + n2又又 二叉树上分支总数二叉树上分支总数 b = n1+2n2 而而 b = n-1 = n0 + n1 + n2 - 1 由此,由此, n0 = n2 + 1 。6.2 二叉树的类型定义二叉树的类型定义两类特殊的二叉树:两类特殊的二叉树:满二叉树:指的是深度为满二叉树:指的是深度为k且含且含有有2k-1个结点的二叉树。个结点的二叉树。完全二叉树:树中所含的 n 个结点和满二叉树中编号为 1 至 n 的结点一一对
18、应。123456789101112131415abcdefghij6.2 二叉树的类型定义二叉树的类型定义 性质性质 4 : 具有具有 n 个结点的完全二叉树的深度为个结点的完全二叉树的深度为 log2n +1 。证明:证明:设完全二叉树的深度为设完全二叉树的深度为 k 则根据第二条性质得则根据第二条性质得 2k-1 n 2k 即即 k-1 log2 n n,则该结点无左孩子,则该结点无左孩子, 否则,编号为否则,编号为 2i 的结点为其左孩子结点;的结点为其左孩子结点;(3) 假设假设 2i+1n,则该结点无右孩子结点,则该结点无右孩子结点, 否则,编号为否则,编号为2i+1 的结点为其右孩
19、子结点。的结点为其右孩子结点。6.2 二叉树的类型定义二叉树的类型定义6.2.3 二叉树的存储结构二叉树的存储结构二、二叉树的链式存储表示二、二叉树的链式存储表示一、一、 二叉树的顺序存储表示二叉树的顺序存储表示6.2 二叉树的类型定义二叉树的类型定义#define MAX_TREE_SIZE 100 / 二叉树的最大结点数二叉树的最大结点数typedef TElemType SqBiTreeMAX_ TREE_SIZE; / 0号单元存储根结号单元存储根结点点SqBiTree bt;一、一、 二叉树的顺序存储表示二叉树的顺序存储表示 所谓二叉树的顺序存储,就是用一组连续的存储单元存所谓二叉树
20、的顺序存储,就是用一组连续的存储单元存放二叉树中的结点。一般是按照二叉树结点从上至下、从放二叉树中的结点。一般是按照二叉树结点从上至下、从左到右的顺序存储。左到右的顺序存储。例如例如: A B D C E F 0 1 2 3 4 5 6 7 8 9 10 11 12 13ABCDEF14013266.2 二叉树的类型定义二叉树的类型定义二、二叉树的链式存储表示二、二叉树的链式存储表示1. 1. 二叉链表二叉链表2三叉链表三叉链表3 3双亲链表双亲链表4线索链表线索链表6.2 二叉树的类型定义二叉树的类型定义lchild data rchild结点结构结点结构:1. 1. 二叉链表二叉链表ADE
21、BCF root6.2 二叉树的类型定义二叉树的类型定义typedef struct BiTNode / 结点结构结点结构 TElemType data; struct BiTNode *lchild, *rchild; / 左右孩子指针左右孩子指针 BiTNode, *BiTree;lchild data rchild结点结构结点结构:C 语言的类型描述如下:6.2 二叉树的类型定义二叉树的类型定义 typedef struct TriTNode / 结点结构 TElemType data; struct TriTNode *lchild, *rchild; / 左右孩子指针 struct
22、TriTNode *parent; /双亲指针 TriTNode, *TriTree;parent lchild data rchild2、三叉链表、三叉链表结点结构结点结构:C 语言的类型描述如下:6.2 二叉树的类型定义二叉树的类型定义0123456 data parent结点结构结点结构:3 3双亲链表双亲链表LRTagLRRRLB2C0A -1D2E3F46.2 二叉树的类型定义二叉树的类型定义 C语言描述 typedef struct BPTNode / 结点结构 TElemType data; int *parent; / 指向双亲的指针 char LRTag; / 左、右孩子标志
23、域 BPTNode; typedef struct BPTree / 树结构 BPTNode nodesMAX_TREE_SIZE; int num_node; / 结点数目 int root; / 根结点的位置 BPTree;6.2 二叉树的类型定义二叉树的类型定义6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树6.3.1 二叉树的遍历二叉树的遍历6.3.2 线索二叉树线索二叉树6.3.1 二叉树的遍历二叉树的遍历一、问题的提出一、问题的提出 “遍历是任何类型均有的操作,对线性结构而言,只有一条搜索路径(因为每个结点均只有一个后继),故不需要另加讨论。而二叉树是非线性结构,每个结点有
24、两个后继,则存在如何遍历即按什么样的搜索路径遍历的问题。对对“二叉树而言,可以有三条搜索路径:二叉树而言,可以有三条搜索路径: 1 先上后下的按层次遍历; 2 先左子树后右子树的遍历; 3 先右子树后左子树的遍历。6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树二、先左后右的遍历算法二、先左后右的遍历算法先根序的遍历算法先根序的遍历算法中根序的遍历算法中根序的遍历算法后根序的遍历算法后根序的遍历算法6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 若二叉树为空树,则空操作;否则, (1访问根结点; (2先序遍历左子树; (3先序遍历右子树。 先根序的遍历算法:先根序的遍历算法:
25、中根序的遍历算法:中根序的遍历算法: 若二叉树为空树,则空操作;否则, (1中序遍历左子树; (2访问根结点; (3中序遍历右子树。6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 若二叉树为空树,则空操作;否则, (1后序遍历左子树; (2后序遍历右子树; (3访问根结点。后根序的遍历算法:后根序的遍历算法:6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树三、算法的递归描述三、算法的递归描述1、先序遍历递归算法、先序遍历递归算法Status Preorder (BiTree T, void( *visit)(TElemType& e) / 先序遍历二叉树先序遍历二叉树
26、 if (T) visit(T-data); / 访问结点访问结点 Preorder(T-lchild, visit); / 遍历左子树遍历左子树 Preorder(T-rchild, visit);/ 遍历右子树遍历右子树 2、中序遍历递归算法、中序遍历递归算法 。将。将 visit(T-data);语句放在中间;语句放在中间; 3、 后序遍历递归算法。将后序遍历递归算法。将 visit(T-data);语句放在最后。语句放在最后。 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树四、中序遍历算法的非递归描述四、中序遍历算法的非递归描述BiTNode *GoFarLeft(BiTre
27、e T, Stack *S) if (!T ) return NULL; while (T-lchild ) Push(S, T); T = T-lchild; return T;void Inorder_I(BiTree T, void (*visit) (TelemType& e) Stack *S; t = GoFarLeft(T, S); / 找到最左下的结点找到最左下的结点 while(t) visit(t-data); if (t-rchild) t = GoFarLeft(t-rchild, S); else if ( !StackEmpty(S ) / 栈不空时退栈栈不
28、空时退栈 t = Pop(S); else t = NULL; / 栈空表明遍历结束栈空表明遍历结束 / while/ Inorder_I 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树五、遍历算法的应用举例五、遍历算法的应用举例1 1、统计二叉树中叶子结点的个数、统计二叉树中叶子结点的个数 ( (先序遍历先序遍历) )2 2、求二叉树的深度、求二叉树的深度( (后序遍历后序遍历) )3 3、复制二叉树、复制二叉树( (后序遍历后序遍历) )4 4、建立二叉树的存储结构、建立二叉树的存储结构6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树1、统计二叉树中叶子结点的个数、统计二
29、叉树中叶子结点的个数算法基本思想算法基本思想: : 先序(或中序或后序)遍历二叉树,在遍历过程中查找叶子结点,并计数。由此,需在遍历算法中增添一个“计数的参数,并将算法中“访问结点的操作改为:若是叶子,则计数器增1。void CountLeaf (BiTree T, int& count) if ( T ) if (!T-lchild)& (!T-rchild) count+; / 对叶子结点计数对叶子结点计数 CountLeaf( T-lchild, count); CountLeaf( T-rchild, count); / if / CountLeaf6.3 二叉树的遍历
30、和线索二叉树二叉树的遍历和线索二叉树2、求二叉树的深度、求二叉树的深度(后序遍历后序遍历)算法基本思想算法基本思想: : 从二叉树深度的定义可知,二叉树的深度应为其左、右子树深度的最大值加1。由此,需先分别求得左、右子树的深度,算法中“访问结点的操作为:求得左、右子树深度的最大值,然后加 1 。 首先分析二叉树的深度和它的左、右子树深度之间的关系。int Depth (BiTree T ) / 返回二叉树的深度返回二叉树的深度 if ( !T ) depthval = 0; else depthLeft = Depth( T-lchild ); depthRight= Depth( T-rch
31、ild ); depthval = 1 + (depthLeft depthRight ? depthLeft : depthRight); return depthval;6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树ABCDEFGHKA3、复制二叉树、复制二叉树 (后序遍历后序遍历) B E C D F G H K newT基本操作为:生成一个结点基本操作为:生成一个结点6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树BiTNode *GetTreeNode(TElemType item, BiTNode *lptr , BiTNode *rptr ) if (!(T =
32、 (BiTNode*)malloc(sizeof(BiTNode) exit(1); T- data = item; T- lchild = lptr; T- rchild = rptr; return T; 生成一个二叉树的结点生成一个二叉树的结点(其数据域为其数据域为item,左指针域为左指针域为lptr,右指针域为右指针域为rptr)BiTNode *CopyTree(BiTNode *T) if (!T ) return NULL; if (T-lchild ) newlptr = CopyTree(T-lchild); /复制左子树 else newlptr = NULL; if (
33、T-rchild ) newrptr = CopyTree(T-rchild); /复制右子树 else newrptr = NULL; newT = GetTreeNode(T-data, newlptr, newrptr); return newT; / CopyTree6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 以字符串的形式以字符串的形式 根根 左子树左子树 右子树定义一棵二叉树右子树定义一棵二叉树例如例如: :ABCD以空白字符以空白字符“ ”表示表示A(B( ,C( , ),D( , )空树空树只含一个根结点的二叉树只含一个根结点的二叉树A以字符串以字符串“A A ”
34、表示表示以下列字符串表示以下列字符串表示4 4、建立二叉树的存储结构、建立二叉树的存储结构 不同的定义方法相应有不同的存储结构的建立算法不同的定义方法相应有不同的存储结构的建立算法6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树A B C D A BCDATBCD算法执行过程6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树Status CreateBiTree(BiTree &T) scanf(&ch); if (ch= ) T = NULL; else if (!(T = (BiTNode *)malloc(sizeof(BiTNode) exit(OVERF
35、LOW); T-data = ch; / 生成根结点生成根结点 CreateBiTree(T-lchild); / 构造左子树构造左子树 CreateBiTree(T-rchild); / 构造右子树构造右子树 return OK; / CreateBiTree6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 按给定的表达式建相应二叉树按给定的表达式建相应二叉树由先缀表示式建树由先缀表示式建树 例如:已知表达式的先缀表示式例如:已知表达式的先缀表示式 -+ a b c / d e由原表达式建树由原表达式建树 例如:已知表达式例如:已知表达式 (a+b)c d/e6.3 二叉树的遍历和线
36、索二叉树二叉树的遍历和线索二叉树对应先缀表达式 -+ a b c / d e的二叉树abcde- -+/特点:特点: 操作数为叶子结点运算符为分支结点操作数为叶子结点运算符为分支结点6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树scanf(&ch);if ( In(ch, 字母集字母集 ) 建叶子结点建叶子结点;else 建根结点建根结点; 递归建左子树递归建左子树; 递归建右子树递归建右子树; 由先缀表示式建树的算法的基本操作:由先缀表示式建树的算法的基本操作:6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树a+b(a+b)c d/ea+bc 分析表达式和二叉树的关
37、系分析表达式和二叉树的关系:ab+abc+abc+(a+b)cabcde- -+/6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树基本操作基本操作:scanf(&ch);if (In(ch, 字母集字母集 ) 建叶子结点建叶子结点; 暂存暂存; else if (In(ch, 运算符集运算符集) 和前一个运算符比较优先数和前一个运算符比较优先数; 若当前的优先数若当前的优先数“高高”,则暂存,则暂存; 否则建子树否则建子树; 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树void CrtExptree(BiTree &T, char exp ) InitSta
38、ck(S); Push(S, #); InitStack(PTR); p = exp; ch = *p; while (!(GetTop(S)=# & ch=#) if (!IN(ch, OP) CrtNode( t, ch ); / 建叶子结点并入栈建叶子结点并入栈 else if ( ch!= # ) p+; ch = *p; / while Pop(PTR, T); / CrtExptree 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树六层次遍历六层次遍历 按照自上而下从根结点开始),从左到右同一按照自上而下从根结点开始),从左到右同一层的顺序逐层访问二叉树上的所有结
39、点,这样的遍历称为层的顺序逐层访问二叉树上的所有结点,这样的遍历称为按层次遍历。按层次遍历。 按层次进行遍历时,当一层结点访问完后,接着访按层次进行遍历时,当一层结点访问完后,接着访问下一层的结点,先遇到的结点先访问,这与队列的操作原问下一层的结点,先遇到的结点先访问,这与队列的操作原则是一致的。因此,在进行层次遍历时,可设置一个数组来则是一致的。因此,在进行层次遍历时,可设置一个数组来模拟队列,用于保存被访问结点的子结点的地址。遍历从二模拟队列,用于保存被访问结点的子结点的地址。遍历从二叉树的根结点开始,首先将根结点指针入队列,然后从队头叉树的根结点开始,首先将根结点指针入队列,然后从队头取
40、出一个元素,每取一个元素,执行下面两个操作:取出一个元素,每取一个元素,执行下面两个操作: (1 1访问该元素所指结点;访问该元素所指结点; (2 2若该元素所指结点的左、右孩子结点非空,则将若该元素所指结点的左、右孩子结点非空,则将该元素所指结点的左孩子指针和右孩子指针依次入队。该元素所指结点的左孩子指针和右孩子指针依次入队。 此过程不断进行,直到队空为止。在下面的层次遍此过程不断进行,直到队空为止。在下面的层次遍历算法中,以二叉链表方式存储,一维数组历算法中,以二叉链表方式存储,一维数组qMAXLENqMAXLEN用以实用以实现队列,现队列,lchildlchild和和rchildrchi
41、ld分别是被访问结点的左、右指针。分别是被访问结点的左、右指针。6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树void Levelorder(BT *T) / 按层次遍历二叉树按层次遍历二叉树BT int i,j; BT *qMAXLEN,*p; / 设置一个数组来模拟队列设置一个数组来模拟队列 p=T; if (p!=NULL) / 若二叉树非空,则根结点地址入队若二叉树非空,则根结点地址入队 i=1;qi=p;j=2; while (i!=j) p=qi;printf(p-data); / 访问队首结点的数据域访问队首结点的数据域 if( p-lchild!=NULL) / 将队
42、首结点的左孩子结点入队列将队首结点的左孩子结点入队列 qj=p-lchild; j+; if(p-rchild!=NULL) / 将队首结点的右孩子结点入队列将队首结点的右孩子结点入队列 qj=p-rchild;j+; i+ ; 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 先序遍历的序列:先序遍历的序列: A B D G E H C F I A B D G E H C F I K K 中序遍历的序列:中序遍历的序列: D G B H E A F K I D G B H E A F K I C C 后序遍历的序列:后序遍历的序列: G D H E B K I F C G D H E
43、 B K I F C A A 层次遍历的序列:层次遍历的序列: A B C D E F G H I A B C D E F G H I K KABCIKFEDHG例例 : 如图所示二叉树,求它的先序遍历、中序遍历、后序遍历和如图所示二叉树,求它的先序遍历、中序遍历、后序遍历和层次遍历。层次遍历。6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 不难证明:n 个结点的二叉树有n+1个空指针域。也就是说一个具有n个结点的二叉树,若采用二叉链表存储结构,在其总共2n个指针域中只有n-1个指针域是用来存储结点子树的地址,而另外n+1个指针域存放的都是空指针域。可以充分利用二叉链表存储结构中的那
44、些空指针域,来保存结点在某种遍历序列中的直接前趋和直接后继的地址信息。 指向直接前趋结点或指向直接后继结点的指针称为线索Thread),带有线索的二叉树称为线索二叉树。对二叉树以某种次序遍历使其变为线索二叉树的过程称为线索化。 A B A 单结点的二叉链表图单结点的二叉链表图 两个结点的二叉链表两个结点的二叉链表一、何谓线索二叉树?一、何谓线索二叉树?6.3.2 线索二叉树线索二叉树6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树例如例如: :先序序列先序序列: : A B C D E F G H K A B C D E F G H K中序序列中序序列: : B D C A H G K
45、 F E B D C A H G K F E后序序列后序序列: : D C B H K G F E A D C B H K G F E A遍历二叉树的结果是,遍历二叉树的结果是, 求得结点的一个线性序列。求得结点的一个线性序列。ABCDEFGHK6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树指向该线性序列中的指向该线性序列中的“前驱和前驱和 “后继后继” 的指针,称作的指针,称作“线索线索”与其相应的二叉树,称作与其相应的二叉树,称作 “线索二叉树线索二叉树”包含包含 “线索线索” 的存储结构,称作的存储结构,称作 “线索链表线索链表”A B C D E F G H K D C B
46、E 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树对线索链表中结点的约定:对线索链表中结点的约定: 在二叉链表的结点中增加两个标志域,并作如下规定:在二叉链表的结点中增加两个标志域,并作如下规定: 若该结点的左子树不空,则若该结点的左子树不空,则Lchild域的指针指向其左子树,域的指针指向其左子树, 且左标且左标志域的值为志域的值为“指针指针 Link”;否则,;否则,Lchild域的指针指向其域的指针指向其“前驱前驱”, 且左标且左标志的值为志的值为“线索线索 Thread” 。 若该结点的右子树不空,则若该结点的右子树不空,则rchild域的指针指向其右子树,域的指针指向其右子
47、树, 且右标志且右标志域的值为域的值为 “指针指针 Link”;否则,;否则,rchild域的指针指向其域的指针指向其“后继后继”, 且右标志且右标志的值为的值为“线索线索 Thread”。如此定义的二叉树的存储结构称作。如此定义的二叉树的存储结构称作“线索链表线索链表”。 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树typedef struct BiThrNod TElemType data; struct BiThrNode *lchild, *rchild; / 左右指针 PointerThr LTag, RTag; / 左右标志 BiThrNode, *BiThrTree;
48、线索链表的类型描述: typedef enum Link, Thread PointerThr; / Link=0:指针,指针,Thread=1:线索线索6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树: for ( p = firstNode(T); p; p = Succ(p) ) Visit (p); 由于在线索链表中添加了遍历中得到的“前驱和“后继的信息,从而简化了遍历的算法。二、线索链表的遍历算法二、线索链表的遍历算法6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树例如例如: 对中序线索化链表的遍历算法对中序线索化链表的遍历算法 中序遍历的第一个结点中序遍历的第一个结
49、点 ? 在中序线索化链表中结点的后继在中序线索化链表中结点的后继 ?左子树上处于左子树上处于“最左下最左下”(没有左子树的结点。(没有左子树的结点。若无右子树,则为后继线索所指结点;若无右子树,则为后继线索所指结点;否则为对其右子树进行中序遍历时访问的第一个结点。否则为对其右子树进行中序遍历时访问的第一个结点。6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树void InOrderTraverse_Thr(BiThrTree T, void (*Visit)(TElemType e) /中序遍历二叉线索树中序遍历二叉线索树T的非递归算法的非递归算法 p = T-lchild; / p指
50、向根结点指向根结点 while (p != T) / 空树或遍历结束时,空树或遍历结束时,p=T while (p-LTag=Link) p = p-lchild; / 第一个结点第一个结点 while (p-RTag=Thread & p-rchild!=T) p = p-rchild; Visit(p-data); / 访问后继结点访问后继结点 p = p-rchild; / p进至其右子树根进至其右子树根 / InOrderTraverse_Thr6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 在中序遍历过程中修改结点的在中序遍历过程中修改结点的左、右指针域,以保存当前
51、访问结左、右指针域,以保存当前访问结点的点的“前驱和前驱和“后继信息。遍历后继信息。遍历过程中,附设指针过程中,附设指针pre, 并始终保并始终保持指针持指针pre指向当前访问的、指针指向当前访问的、指针p所指结点的前驱。所指结点的前驱。三、如何建立线索链表?三、如何建立线索链表?6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树void InThreading(BiThrTree p) if (p) / 对以对以p为根的非空二叉树进行线索化为根的非空二叉树进行线索化 InThreading(p-lchild); / 左子树线索化左子树线索化 if (!p-lchild) / 建前驱线索
52、建前驱线索 p-LTag = Thread; p-lchild = pre; if (!pre-rchild) / 建后继线索建后继线索 pre-RTag = Thread; pre-rchild = p; pre = p; / 坚持坚持 pre 指向指向 p 的前驱的前驱 InThreading(p-rchild); / 右子树线索化右子树线索化 / if / InThreading6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树Status InOrderThreading(BiThrTree &Thrt, BiThrTree T) / 构建中序线索链表构建中序线索链表 i
53、f (!(Thrt = (BiThrTree)malloc(sizeof( BiThrNode) exit (OVERFLOW); Thrt-LTag = Link; Thrt-RTag =Thread; Thrt-rchild = Thrt; / 添加头结点添加头结点 return OK; / InOrderThreading 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树if (!T) Thrt-lchild = Thrt; else Thrt-lchild = T; pre = Thrt; InThreading(T); pre-rchild = Thrt; / 处理最后一个结
54、点处理最后一个结点 pre-RTag = Thread; Thrt-rchild = pre; 6.3 二叉树的遍历和线索二叉树二叉树的遍历和线索二叉树 6.4 树和森林树和森林的表示方法的表示方法6.4.1 6.4.1 树的三种存储结构树的三种存储结构6.4.2 6.4.2 森林和二叉树的对应关系森林和二叉树的对应关系6.4.2 6.4.2 树和森林的遍历树和森林的遍历6.4.1 6.4.1 树的三种存储结构树的三种存储结构一、双亲表示法一、双亲表示法二、孩子链表表示法二、孩子链表表示法三、树的二叉链表三、树的二叉链表(孩子孩子-兄弟存储表示法兄弟存储表示法 6.4 树和森林的表示方法树和森
55、林的表示方法ABCDEFG0 A -11 B 02 C 03 D 04 E 2 5 F 26 G 5r=0n=6data parent一、双亲表示法一、双亲表示法: 6.4 树和森林的表示方法树和森林的表示方法 typedef struct PTNode Elem data; int parent; / 双亲位置域 PTNode; data parent#define MAX_TREE_SIZE 100C语言的类型描述语言的类型描述:typedef struct PTNode nodes MAX_TREE_SIZE; int r, n; / 根结点的位置和结点个数根结点的位置和结点个数 PTr
56、ee;结点结构结点结构树结构树结构 6.4 树和森林的表示方法树和森林的表示方法ABCDEFG0 A -11 B 02 C 03 D 04 E 25 F 26 G 4r=0n=6 data firstchild 1 2 34 56二、孩子链表表示法二、孩子链表表示法:-1 0 0 0 2 24 6.4 树和森林的表示方法树和森林的表示方法typedef struct CTNode int child; struct CTNode *next; *ChildPtr; child nextC语言的类型描述语言的类型描述:孩子结点结构孩子结点结构 typedef struct Elem data;
57、ChildPtr firstchild; / 孩子链的头指针 CTBox; data firstchild双亲结点结构双亲结点结构typedef struct CTBox nodesMAX_TREE_SIZE; int n, r; / 结点数和根结点的位置结点数和根结点的位置 CTree;树结构树结构 6.4 树和森林的表示方法树和森林的表示方法ABCDEFG AB C E D F Groot AB C E D F G 三、树的二叉链表三、树的二叉链表 (孩子孩子-兄弟存储表示法兄弟存储表示法 6.4 树和森林的表示方法树和森林的表示方法typedef struct CSNode Elem d
58、ata; struct CSNode *firstchild, *nextsibling; CSNode, *CSTree;C语言的类型描述语言的类型描述: firstchild data nextsibling结点结构结点结构: 6.4 树和森林的表示方法树和森林的表示方法 6.4.2 森林和二叉树的对应关系森林和二叉树的对应关系设森林设森林 F = ( T1, T2, , Tn ); T1 = (root,t11, t12, , t1m);二叉树二叉树 B =( LBT, Node(root), RBT ); 6.4 树和森林的表示方法树和森林的表示方法由森林转换成二叉树的转换规则为由森林
59、转换成二叉树的转换规则为:假设 F = ,那么 B = ; 否则, 由 ROOT( T1 ) 对应得到 Node(root); 由 (t11, t12, , t1m ) 对应得到 LBT; 由 (T2, T3, Tn ) 对应得到 RBT。 6.4 树和森林的表示方法树和森林的表示方法由二叉树转换为森林的转换规则为:由二叉树转换为森林的转换规则为:假设 B = , 那么 F = ; 否则, 由 Node(root) 对应得到 ROOT( T1 ); 由LBT 对应得到 ( t11, t12, ,t1m); 由RBT 对应得到 (T2, T3, , Tn)。 由此,树的各种操作均可对应二叉树的操
60、作来完成。应当注意的是,和树对应的二叉树,其左、右子树的概念已改变为: 左是孩子,右是兄弟。 6.4 树和森林的表示方法树和森林的表示方法6.4.3 树和森林的遍历树和森林的遍历一、树的遍历一、树的遍历二、森林的遍历二、森林的遍历 6.4 树和森林的表示方法树和森林的表示方法按层次遍历按层次遍历:先根先根(次序次序)遍历遍历:后根后根(次序次序)遍历遍历: 若树不空,则先访问根结点,然后依次先根遍历各棵子树。若树不空,则先访问根结点,然后依次先根遍历各棵子树。 若树不空,则先依次后根遍历各棵子树,然后访问根结点。若树不空,则先依次后根遍历各棵子树,然后访问根结点。 若树不空,则自上而下自左至右访问树中每个结点。若树不空,则自上而下自左至右访问树中每个结点。一、树的遍历有三条搜索路径一、树的遍历有三条搜索路径:6.4.3 树和森林的遍历树和森林的遍历 6.4 树和森林的表
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 4944-2026玻璃纤维增强塑料层合板层间拉伸强度试验方法
- 吴文英《梦窗词》讲解
- 苻坚的前秦霸业
- DB51∕T 3366-2026 发电用燃料电池堆电性能测试规范
- 2026年语文教学方法策略研究报告
- 2026年固定资产规范化管理方案设计
- 2026年奶茶店经营策略与管理
- 2026年安全防范技术未来发展趋势分析
- 2026年实验安全问题及其教学研究
- 2026年导游职业发展初期目标
- 2026年高考真题-语文(全国二卷) 含解析
- 2026年湖南岳阳市初二学业水平地生会考真题试卷(含答案)
- 2026春人教版三年级下册语文全册看拼音写词语专项练习(可打印)
- 2026年外贸应聘人员测试题及答案
- 2026云南临沧国投宏华招聘综合业务开单员3人备考题库附答案详解(典型题)
- 西安铁路局集团有限公司招聘笔试题库2026
- 2025福建福州市闽侯县水务投资发展有限公司招聘3人笔试历年参考题库附带答案详解
- 2026年生物制药疫苗研发关键技术知识考察试题及答案解析
- 街道办公室工作制度
- 无废工厂培训资料
- 岳飞传课件教学课件
评论
0/150
提交评论