数据结构课件:第4章 树1_第1页
数据结构课件:第4章 树1_第2页
数据结构课件:第4章 树1_第3页
数据结构课件:第4章 树1_第4页
数据结构课件:第4章 树1_第5页
已阅读5页,还剩87页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、4.1树的基本概念4.2二叉树4.3线索二叉树4.4树和森林4.5压缩与哈夫曼树4.6 应用第四章 树树结构在客观世界中大量存在,如家谱、行政组织机构等都可用树形象地表示。JoeJohnMaryAnnChrisSueMaryMary企业管理机构 在层次中地位最高的人(此处为总裁)在图中位置最高。在层次中地位次之的(即副总裁)在图中位于总裁之下等等。副总裁为总裁的下属,总裁是他们的上级。每个副总裁都有自己的下属,而其下属又有自己的下属。企业管理结构总裁财务副总裁市场副总裁开发副总裁销售副总裁. 递归定义定义4.1: 一个树(或树形)就是一个有限非空的结点集合T,其中:有一个特别标出的被称为该树(

2、或树形)之根root(T)的结点;其余结点(根除外)被分成m 0 个不相交的集合T1,T2,Tm,且T1,T2,Tm又都是树(或树形)。树(或树形)T1,T2,Tm被称作root(T)的子树(或子树形)。一、树的定义图4.1为一棵由根结点A出发的树,其中,A有三个子结点B、C和D;B有一个子结点E;E有一个子结点F;C有两个子结点G和H;D有一个子结点I; F,G,H,I是叶结点,因为它们没有子结点。从A到F的路径为A-B-E-F。AECDBIHGF图4.1 树EBF(A)G(B)CHG(C)图4.2 子树 若断掉一个结点与其父结点的连接,把该结点和它的子孙们单独拿出,就是一棵以该结点为根结点

3、的树,我们称之为“子树”。图4.1.2中的(A)、(B)、(C)均是图4.1所示树的子树。树的相关术语1度一个结点的子结点的数目,称为该结点的度或次数。一棵树的度为maxi=1, n D (i),其中n为树中结点总数,i指树中的第i个结点,D(i)表结点i的度。2叶结点、分支结点度为0的结点被称为叶结点;度0的结点被称为分支结点。在图4.1中:B有一个子结点E,度为1;A有三个子结点B、C和D(换言之,A是B、C和D的父结点),度为3,故这棵树的度也为3 .3结点的层数树形T中结点的层数递归定义如下: root(T)层数为零; 其余结点的层数为其前驱结点的层数加1 .AECDBIHGF层次0层

4、次1层次2层次3树的层数4路径树形中结点间的连线被称为边。若树形T中存在结点序列vm vm+1 vmk,1 k T的最大层数,满足vi+1是vi(m i mk1)的子结点,则称此结点序列为vm到vmk的路径,该路径所经历的边数nm被称为路径长度。5. 子孙结点、祖先结点一棵树中若存在结点vm到vn的路径,则称vn为vm的子孙结点,vm为vn的祖先结点。 不难看出,一个结点到它的某个子孙结点有且仅有一条路径。树中结点之间的父子关系具有如下特征:(1)树中任一结点都可以有零个或多个直接后继(即子结点),但至多只能有一个直接前驱(即父结点)。(2)树中只有根结点无前驱,它是始结点;叶结点无后继,它们

5、是终结点。(3)树中某些结点之间具有父子关系或者祖先、子孙关系,祖先、子孙关系是对父子关系的扩展,一些结点之间,如兄弟结点(同一个父亲的诸子结点被称为兄弟结点)之间就没有这种关系。6树的高度 树的高度为maxi=1, n NL (i),其中n为树中结点总数,i指树中第i个结点,NL(i)之值为结点i的层数。 树的高度是指树中结点的最大层数。7 有序树和无序树 树中结点的各棵子树T1,T2,是有次序的,即为有序树,否则为无序树。8 森林 森林是m (m0)棵互不相交的树的集合。树的表示 1.集合嵌套表示法2.凹入表示法3.广义表表示法4.树形表示法ACBDEABCDEA(B,C(D,E)ABCD

6、E1243与线性结构的比较 线性结构 树结构第一个数据元素 根结点 (无前驱) (无前驱)最后一个数据元素 多个叶子结点 (无后继) (无后继)其它数据元素 树中其它结点(一个前驱、一个后继) (一个前驱、多个后继)树的特点: 有一个总根。 没有分枝相交。 树有层次。树的基本操作1、创建树:CREATE_TREE(T)2、判树空:TREEEMPTY(T)3、求根:ROOT(T) 4、求树的高度:TREEDEPTH(T)5、 求某结点的兄弟: BROTHERS(T)6、求结点的双亲:PARENT(T)7、求结点的孩子:CHILD(T,e,i)8、遍历树:TRAVERSAL(T) 9、在树T中搜索

7、数据域为item的结点:SEARCH(T,item,i)4.1树的基本概念4.2二叉树4.3线索二叉树4.4树和森林4.5压缩与哈夫曼树4.6 应用第四章 树4.2二叉树 4.2.1 二叉树的定义和主要性质 4.2.2 二叉树的顺序存储 4.2.3 二叉树的链接存储 4.2.4 二叉树的遍历 4.2.5 二叉树遍历的应用4.2.1 二叉树的定义和主要性质二叉树的定义:二叉树是结点的有限集合,它或者是空集,或者由一个根及两个不相交的称为这个根的左、右子树的二叉树构成。 二叉树的特征 (1) 二叉树每个结点最多有2个子结点; (2) 二叉树的子树有左右之分。二叉树的五种不同形态 (a) (b) (

8、c) (d) (e)树与二叉树的主要区别:(1)二叉树每个结点最多有 2 个子结点,树则无此限制;(2) 二叉树中结点的子树分成左子树和右子树,即使某结点只有一棵子树,也要指明该子树是左子树,还是右子树,就是说二叉树是有序的;(3) 树不能为空,即它至少有一个结点,而一棵二叉树可以是空的(或者说二叉树可以为空集)。 含有3个结点的不同二叉树 (a) (b) (c) (d) (e)二叉树的性质引理4.1 二叉树中层数为i的结点至多有2i个,i 0。(当根结点为1层时,有2i-1个结点。)证明:用数学归纳法。当i=0时,仅有一个根结点,其层数为0,因此i=0时引理成立。假定当i=k(k0)时引理成

9、立,即第j层至多有2k个结点。对于二叉树的任意结点,其子结点个数最大为2,故第k+1层至多有 2*2k= 2k+1 个结点,因此当 i=k+1时,引理成立。由数学归纳法可知,对于所有的i0,均有“第 i 层上至多有 2i 个结点”。证毕。引理4.2 高度为k的二叉树中至多有2k+1-1 (k 0)个结点。 (当根结点为1层时,有2k -1个结点。)证明:根据引理4.1 第0层上至多有20个结点,第1层上至多有21个结点, ,第k层上至多有2k个结点,因此,高度为k的二叉树中至多有20 21+ 2k= 2k+1-1 个结点。证毕。高度为k (k 1)的二叉树中至少有k1个结点。含有k (k 1)

10、个结点的二叉树高度至多为k1 . 有4个结点、高度为3的二叉树CABD引理4.3 设T是由n个结点构成的二叉树,其中叶子结点个数为n0,度为2的结点个数为n2,则有:n0n21证明:设度为1的结点有n1个,总结点个数为n,总边数为e,则: n=n0+n1+n2 (1) e=n-1 (2) e=2n2+n1 (3) 因此,有n0+n1+n2-1=2n2+n1 n0=n2+1证毕。定义4.4 一棵非空高度为k( k 0)的满二叉树,是有2k+11个结点的二叉树。654372981013111214151高度为k(非空)二叉树至多有2k+11个结点。满二叉树的特点是: 叶结点都在第k层上; 每个分支

11、结点都有两个子结点; 叶结点的个数等于非叶结点个数加1 定义4.5 一棵包含n个结点高为k的二叉树T,当按层次顺序编号T的所有结点,对应于一棵高为k的满二叉树中编号由1至n的那些结点时,T被称为完全二叉树。65437298101具有n个结点高为k的完全二叉树的特点是: 树中只有最下面两层结点的度可以小于2; 树中最下面一层的结点都集中在该层最左边的若干位置上(满二叉树意义上); 树中叶结点只能在层数最大的两层上出现,即存在一个非负整数k使得树中每个叶结点在第k层或第k 1层; 对树中所有结点,按层次顺序,用自然数从1开始编号,仅仅编号最大的非叶结点可以没有右孩子,其余非叶结点都有两个孩子结点。

12、 树中所有结点对应于高度为k的满二叉树中编号由1至n的那些结点。引理4.4 若将一颗具有n个结点的完全二叉树按层次次序从1开始编号,则对编号为i (1i n)的结点有: 若i1,则编号为i的结点的父结点的编号为 i/2 。若2in,则编号为i的结点的左孩子的编号为 2i,否则 i 无左孩子。若2i+1n,则i结点的右孩子结点编号为2i+1,否则 i 无右孩子。用归纳法证明 若i=1,如果n2,则左孩子的编号显然为2. 假定对所有满足ji的j,已知j的左孩子编号为2j. 那么对结点i+1,我们证明其左孩子编号为2(i+1). 如果2(i+1)n,则由层次次序得知,i+1的左孩子之前的两个结点是i

13、的左孩子和右孩子,因为i的左孩子编号为2i(归纳假设),故i的右孩子编号为2i+1,从而i+1的左孩子编号为2i+2= 2(i+1).证毕引理4.5 具有n个结点的完全二叉树的高度是 log2n .证明: 设二叉树高度为k,由定义知,完全二叉树的结点个数介于高度为k-1和高度为k的满二叉树的结点数之间,即有: 2k-1 n2k+1-1 从而有2kn 2k+1,即klog2n k+1,因为k为整数,故有k= log2n .证毕请注意: 当根结点的层数为1时,树的高度为 log2n +1 。4.2二叉树 4.2.1 二叉树的定义和主要性质 4.2.2 二叉树的顺序存储 4.2.3 二叉树的链接存储

14、 4.2.4 二叉树的遍历 4.2.5 二叉树遍历的应用要存储一棵二叉树,必须存储其所有结点的数据信息、左孩子和右孩子地址,既可用顺序结构存储,也可用链接结构存储。二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中,同时反映出二叉树中结点间的逻辑关系。4.2.2 二叉树的顺序存储 对于完全二叉树,结点的层次顺序反映了其结构,可按层次顺序给出一棵完全二叉树之结点的编号,结点编号恰好反映了结点间的逻辑关系,事实上,这就是完全二叉树的顺序存储方法。 只要对二叉树之结点按照层次顺序进行编号,就可利用一维数组A来存储一棵含有n个结点的完全二叉树,其中A1存储二叉树的根结点,A

15、i存储二叉树中编号为i的结点,并且结点Ai的左孩子(若存在)存放在A2i处,而Ai的右孩子(若存在)存放在A2i1处。完全二叉树的顺序存储 A1A2A3A4A5A6 A7 A8 A9A10941766125236270493131 23 12 66 94 17 5 70 62 49 这种顺序存储方式是完全二叉树最简单、最节省空间的存储方式。它实际上只存储了结点信息域之值,而未存储其左孩子和右孩子地址,通过计算可找到它的左孩子、右孩子和父结点,寻找子孙结点和祖先结点也非常方便。但这种方法应用到非完全二叉树时,却有很多缺点。如果采用上述的顺序存储方式,按照层次顺序,对非完全二叉树之结点进行编号,则

16、这时的编号不能与结点一一对应。为此,先加入若干虚结点将其转换成一棵“完全二叉树”,然后再对原来的结点和虚结点统一编号,最后完成顺序存储。但这增加了用于存储虚结点的空间。 一般二叉树必须仿照完全二叉树那样存储。但可能会浪费很多存储空间。一棵n个结点的二叉树,最坏情况下需要2n-1个数组单元。4CB A 25731a1a2a3a4a5A B C a6a74.2二叉树 4.2.1 二叉树的定义和主要性质 4.2.2 二叉树的顺序存储 4.2.3 二叉树的链接存储 4.2.4 二叉树的遍历 4.2.5 二叉树遍历的应用1、 二叉树的链接存储二叉树诸结点被随机存放在内存空间中,结点之间的关系用指针说明。

17、 二叉树的结点结构 二叉树结点包含三个域:数据域data、指针域left和指针域right,其中左、右指针分别指向该结点的左、右孩子结点.leftright data 二叉树的链接存储结构ADCBEFGACBEFDG三叉链表表示法 Left data parent right 二叉树结点类的定义 TemplateClass BinTreeNode friend class BinTree ; private:BinTreeNode *left;BinTreeNode *right; public: T data; 2、链接存储的二叉树的实现 BinTreeNode (const T&item,

18、 BinTreeNode *lptr=NULL, BinTreeNode *rptr=NULL): data(item),left(lptr),right(rptr) / 构造函数 BinTreeNode*GetLeft(void)const return Left; /返回左孩子 BinTreeNode*GetRight(void)const return right; /返回右孩子 void SetLeft(BinTreeNode * L) left = L; / 将左孩子更新为结点 L void SetRight(BinTreeNode * R) right=R; /将右孩子更新为结点

19、R ; 二叉树类BinTree的定义templateclass BinTree private: BinTreeNode * root; /指向根结点 public: BinTree(BinTreeNode * t= NULL ): root(t) /构造函数 BinTree( ) Del (root); /析构函数删除整棵二叉树 BinTreeNode *Father (BinTreeNode * t, BinTreeNode* p); /在以t为根的子树中搜索结点p的父结点int Find (BinTreeNode * & t,const T & item) const; /在以t为根的子

20、树中查找data域为item的结点void DelSubtree (BinTreeNode* t); / 删除以t为根的子树void PreOrder (BinTreeNode *t ) const ; /先根遍历以结点t为根的子树void InOrder (BinTreeNode *t) const ; /中根遍历以t为根的子树void PostOrder (BinTreeNode *t) const ; /后根遍历以结点t为根的子树. 二叉树类BinTree的部分实现 (1) 搜索父结点算法Father ( t, p . q )/在以t为根的二叉树中搜索p的父结点 F1 判断t是否存在及p

21、是否为根结点 IF (t=NULL OR p=t)THEN ( qNULL . RETURN ) . F2 若t为所求 IF left(t)=p OR right(t)=p THEN ( qt . RETURN). F3 递归调用 Father( left(t), p . qL). IF qLNULL THEN qqL . RETURN.) ELSE ( Father(right(t), p . qR). qqR) . ABDCL1L2 二叉树类BinTree的实现 (1) 搜索父结点 / 私有函数 father :返回父结点。 template BinTreeNode * BinNode :

22、 father(BinTreeNode *begin, BinTreeNode * current) 搜索父结点father(BinTreeNode *begin, BinTreeNode * current) BinTreeNode * temp; if( begin = = NULL) return NULL if( begin-left=current| begin-right=current) return begin; if((temp=father(begin-left, current)!= NULL) return temp ; else return father(begin

23、-right,current); L1L2ABDFCE(2)搜索二叉树中符合数据域条件的结点算法Find( t, item . q )Find1. 判断t是否为空或为所求 IF t THEN (q . RETURN. ). IF Data(t)item THEN (q t . RETURN. ).Find2. 递归 Find ( Left(t), item . p ). IF p THEN (q p . RETURN. ). Find (Right(t), item . q ). RETURN.(3)删除结点t及其左右子树算法DST ( t )DST1. t? IF t THEN RETURN

24、 .DST2. troot? IF troot THEN (Del(t) . root . RETURN. )DST3. 找t的父结点q pt . Father(root, p. q).DST4. 修改q的指针域 IF Left(q)p THEN Left(q) . IF Right(q)p THEN Right(q) . DST5. 删除p及其子树 Del(p).算法Del( p )/* 删除结点p及其左右子树 */Del1. p ? IF p THEN RETURN.Del2. 递归删除 Del(Left (p). Del(Right (p). AVAIL p .ABECD4.2二叉树 4

25、.2.1 二叉树的定义和主要性质 4.2.2 二叉树的顺序存储 4.2.3 二叉树的链接存储 4.2.4 二叉树的遍历 4.2.5 二叉树遍历的应用 4.2.4 二叉树的遍历 二叉树的遍历:按照一定次序访问二叉树中所有结点,并且每个结点仅被访问一次的过程。 二叉树的某种(先根、中根、后根或层次)遍历次序是二叉树中结点的一个有序序列,称为二叉树的先根(中根、后根或层次)序列。 1. 二叉树的递归遍历算法遍历方式先根遍历: DLR中根遍历: LDR后根遍历: LRDLDR二叉树 ABDFCE先根遍历序列:A B C D E F中根遍历序列: B D C A F E后根遍历序列: D C B F E

26、 A若二叉树为空,则空操作;否则中根遍历左子树;访问根结点;中根遍历右子树。遍历结果 A / B *C * D +E1)中根遍历(中序遍历)表达式语法树At例*D/E*+CB二叉树中根遍历算法(递归)算法InOrder(t)InOrder1 递归遍历 IF tNULL THEN (InOrder(left(t). PRINT(data(t). InOrder(right(t).) /中序遍历以t为根的子树,C+实现void BinTree:InOrder ( BinTreeNode * t ) if ( t != NULL ) InOrder( tleft ); cout tdata; InO

27、rder ( tright ); 中序遍历结果: A / B *C * D +EAt例*D/E*+CB出栈的条件: t0 ,子程序结束且栈不空出栈。整个程序结束的条件: 子程序结束并且栈为空。2)先根遍历 (前/先序遍历)若二叉树为空,则空操作;否则访问根结点;先根遍历左子树;先根遍历右子树。表达式语法树At例*D/E*+CB二叉树先根遍历算法(递归)算法PreOrder(t)PreOrder1 递归遍历 IF tNULL THEN ( PRINT(data(t). PreOrder(left(t). PreOrder(right(t) ).) /先序遍历以t为根的子树,C+实现void Bi

28、nTree:PreOrder ( BinTreeNode * t ) if ( t != NULL ) cout tdata; PreOrder ( tleft ); PreOrder ( tright ); 3)后根遍历 (后序遍历)若二叉树为空,则空操作;否则后根遍历左子树;后根遍历右子树;访问根结点。二叉树后根遍历算法(递归)算法PostOrder(t)PostOrder1 递归遍历 IF tNULL THEN (PostOrder(left(t). PostOrder(right(t). PRINT(data(t). ) 2. 二叉树的非递归遍历算法 非递归的中根遍历递归算法InOrd

29、er(t)InOrder1 递归遍历 IF tNULL THEN (InOrder(left(t). PRINT(data(t). InOrder(right(t). ) ABECD非递归的中根遍历算法算法NIO( t )NIO1. 初始化 CREATE ( S ). p t . /* CREATE(S) 创建一个空堆栈 */NIO2. 入栈 WHILE p DO ( S p . p Left ( p) . )NIO3. 栈为空? IF S为空 THEN RETURN. ELSE p S .NIO4. 访问p,更新p PRINT (Data ( p ) ). p Right ( p ). NI

30、O5. 返回 GOTO NIO2 .第 72 页图4.12 非递归中根遍历二叉树 (a) 二叉树(b) 中根遍历(a)中二叉树, 堆栈内容变化过程图(b)中略去了进栈过程的描述ABCDEFABAADCCEAF访问D访问A访问C访问FAABA进栈B进栈访问BADD进栈CC进栈E进栈CE访问EF进栈FNIO2. 入栈 WHILE p DO ( S p. p Left ( p).)NIO3. 栈为空? 若S为空,则 RETURN. 否则 p S .NIO4. 访问,更新p 打印 Data(p). pRight(p). 返回NIO2第 72 页非递归的先根遍历算法,与非递归的中根遍历算法类似,区别在于

31、输出语句的位置不同。先根和中根遍历的非递归算法,一个结点仅进栈出栈一次,我们能够判断其输出语句的位置,分别为结点进栈前及出栈后。而后根遍历输出结点的位置应为处理完右子树之后,如果每个结点还是进栈、出栈一次,则无法确定何时输出结点,即其左右子树是否已处理完。非递归的后根遍历算法 设置一个工作栈: 结点所处状态i = 0, 1或2: 0:结点及左右子树均未被访问; 1:遍历左子树; 2:遍历右子树。树中任一结点q都需进栈三次,出栈三次。第一次出栈是为遍历结点q的左子树,第二次出栈是为遍历结点q的右子树,第三次出栈是为访问结点q . 结点 结点状态 i1) 将(根结点,0)压入堆栈。2) 弹栈,对出

32、栈元素(p, i )中标号i进行判断, 若 i0,则将(p,1)压入堆栈;若结点p的左指针不为空,则将(Left(p), 0) 压入堆栈,准备遍历其左子树.若 i1,此时已遍历完结点p的左子树,则将(p,2)压入堆栈;若右指针不为空,则将(Right(p), 0)压入堆栈,准备遍历其右子树.若 i2,此时已遍历完结点p的右子树,访问结点p. 算法NPostOrder(t)NPO1建立堆栈 CREATS(S).NPO2堆栈初始化 S (t,0).NPO3利用栈实现递归 WHILE NOT(StackEmpty(S) DO ( (P,i) S. IF i=0 THEN ( S (P,1). IF

33、left(P) null THEN S (left(P),0) . ) IF i=1 THEN ( S (P,2). IF right (P) null THEN S (right(P),0). ) IF i=2 THEN PRINT(data(P) . ) 非递归的后根遍历算法对左图之二叉树进行后序遍历, 栈S 之变化 访D访BFCABDEWHILE 栈 S 非空 DO /分别简记left、right为 Lt 和 Rt ( ( p , i ) S. IF i 0 THEN S( p , 1). 若 Lt ( p) , 则 S (Lt ( p), 0). IF i 1 THEN S( p ,

34、2). 若 Rt ( p) , 则 S (Rt ( p), 0). IF i 2 THEN PRINT (data( p). ) 第 77 页第 77 页由先根序列和中根序列可以唯一 确定一棵二叉树。例 先根序列 A B C K D E H F 中根序列B K C A H E D F先根序列 A B C K D E H F 中根序列 B K C A H E D FAB CKDEHFABEDCKFHABDCKEHF由后根序列和中根序列可以唯一地确定一棵二叉树。例 后根序列 C E F D B H G A 中根序列 C B E D F A G H后根序列 C E F D B H G A 中根序列C

35、 B E D F A G HACBEDFGHABCDEFGHABCGDEHF3、二叉树的层次遍历按层数由小到大,同层由左向右的次序访问结点。遍历结果: A B E C F DABDFCE通过观察发现,第i层上,若结点x在结点y的左边,则x一定在y之前被访问。同理,第i+1层上,x的子结点一定在y的子结点前被访问。若访问第i层上的所有结点,必须知道该层上所有结点的地址,地址保存在其父结点的left和right指针中。用一个队列来实现。二叉树层次遍历算法需要一个辅助队列具体方法如下:根结点入队.重复本步骤直至队为空:若队非空,取队头结点并访问; 若其左指针不空,将其左孩子入队; 若其右指针不空,将其右孩子入队. ABFEDC算法LevelOrder ( t )LevelOrder1. 建空队 CREATE ( Q ). LevelOrder 2. 入队 p t . IF p THEN Q p .LevelOrder 3. 层次遍历 WHILE Q 非空 D

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论