收藏 分享(赏)

第5章树和二叉树.ppt

上传人:jw66tk88 文档编号:10200945 上传时间:2019-10-18 格式:PPT 页数:123 大小:1.42MB
下载 相关 举报
第5章树和二叉树.ppt_第1页
第1页 / 共123页
第5章树和二叉树.ppt_第2页
第2页 / 共123页
第5章树和二叉树.ppt_第3页
第3页 / 共123页
第5章树和二叉树.ppt_第4页
第4页 / 共123页
第5章树和二叉树.ppt_第5页
第5页 / 共123页
点击查看更多>>
资源描述

1、树型结构是一类重要的非线性数据结构。其中以树和二叉树最为常用,直观看来,树是以分支关系定义的层次结构。树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树来形象表示。树在计算机领域中也得到广泛应用,如在编译程序中,可用树来表示源程序的语法结构。又如在数据库系统中,树形结构也是信息的重要组织形式之一。,本章主要内容,树的逻辑结构; 树的存储结构; 二叉树的逻辑结构; 二叉树的存储结构及实现; 树、森林与二叉树的转换; 二叉树的经典应用哈夫曼树。,5.1 树的逻辑结构,5.1.1 树的定义和基本术语,1 树的定义,树是n(n0)个结点的有限集合。当n0时,称为空树;任意一棵非空树

2、满足以下条件: 有且仅有一个特定的称为根的结点; 当n1时,除根结点之外的其余结点被分成m(m0)个互不相交的有限集合T1,T2,Tm,其中每个集合又是一棵树,并称为这个根结点的子树。,E,A,B,E,C,C,F,D,F,G,(a) 一棵树结构 (b)一个非树结构 (c)一个非树结构,例:,T=A,B,I ,结点A为根结点,子树T1=B,D,E,F,H,I,T2=C,G.,2 树的基本术语,结点的度、树的度、m叉树,结点所拥有的子树的个数称为该结点的度; 树中各结点度的最大值称为该树的度; 称度为m的树为m叉树。,叶子结点、分支结点,度为0的结点称为叶子结点,也称为终端结点; 度不为0的结点称

3、为分支结点,也称为非终端结点。,孩子结点、双亲结点、兄弟结点,树中某结点子树的根结点称为这个结点的孩子结点;反之,这个结点称为它孩子结点的双亲; 具有同一个双亲的孩子结点互称为兄弟。,路径、路径长度 如果一棵树的结点序列n1,n2,nk有如下关系:结点ni是ni+1的双亲(1ik),则把n1,n2,nk称为一条由n1至nk的路径;路径上经过的边的个数称为这条路径的长度。,祖先、子孙 在树中,如果有一条路径从结点x到结点y,那么x就称为y的祖先,而y称为x的子孙。 以某结点为根的子树中的任一结点都是该结点的子孙。,结点的层数、树的深度(高度) 在树中,根结点的层数为1,对其余任何结点,若某结点在

4、第k层结点,则其孩子结点在第k+1层结点; 树中所有结点的最大层数称为树的深度,也称为树的高度。,结点按层编号(层序编号) 将树中结点按照从上层到下层、同层从左到右的次序依次给他们编以从1开始的连续自然数,树的这种编号方式称为层序编号。,有序树和无序树 如果一棵树中结点的各子树从左到右是有次序的,即若交换了某结点各子树的相对位置,则构成不同的树,称这棵树为有序树;反之,称为无序树。,数据结构中讨论的一般都是有序树,森林 m (m0)棵互不相交的树的集合构成森林。 同构 对两棵树,若通过对结点适当地重命名,就可以使这两棵树完全相等(结点对应相等,结点对应关系也相等),则称这两棵树同构。,树的基本

5、术语小结,1层,2层,4层,3层,height = 4,A,C,G,B,D,E,F,K,L,H,M,I,J,结点 结点的度 叶结点 分支结点,子女 双亲 兄弟,祖先 子孙 结点层次,树的深度 树的度 森林,线性结构,树型结构,无前驱,无双亲,一对一 一对多,结点A的度?结点B的度?该树的度?,叶子结点有哪些?分支结点有哪些?,哪些结点是孩子关系?哪些结点是双亲关系?哪些结点是兄弟结点?,练习:,结点A到结点H的路径?,结点H的祖先?结点B的子孙?,结点D的层数为多少?该树的深度为多少?,5.1.2 树的抽象数据类型定义,树的基本操作有: Tree(T):初始化一棵空树T。 Root(x):求结

6、点x所在树的根结点。 Parent(T ,x):求树T中结点x的双亲结点。 Child(T,x,i):求树T中结点x的第i个孩子结点。 RightSibling(T,x):求树T中结点x右兄弟结点。 Insert(T,x,i,s)把以s为根结点的树插入到树T中作为结点x的第 i 棵子树。 Delete(T,x,i)在树T中删除结点x的第i棵子树。 Traverse(T):树的遍历操作,即按某种方式访问树T中的每个结点,且使每个结点只被访问一次。,5.1.3 树的遍历操作,树的遍历是指从根结点出发,按照某种次序访问树中所有结点,使得每个结点被访问一次且仅被访问一次。,如何理解访问一词?,如何理解

7、次序一词?,1. 前序遍历,树的前序遍历操作定义为: 若树为空,则空操作返回;否则 访问根结点; 按照从左到右的顺序前序遍历根结点的每一棵子树。,ABDEHIFCG,2. 后序遍历,树的后序遍历操作定义为: 若树为空,则空操作返回;否则 按照从左到右的顺序后序遍历根结点的每一棵子树; 访问根结点。,DHIEFBGCA,3. 层序遍历,树的层序(广度)遍历操作定义为: 从树的第一层(即根结点)开始,自上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。,ABCDEFGHI,5.2 树的存储结构双亲表示法,双亲表示法是指用一维数组来存储树的各个结点(一般按层序存储),数组中的一个元素对应树

8、中的一个结点,其中包括结点的数据信息以及该结点的双亲在数组中的下标。,其中:data:数据域 parent:指针域,该结点的双亲在数组中的下标,结点结构,结点的C+描述:,const int MaxSize=100; template struct PNodeT data; int parent; ;PNode TreeMaxSize;,例:,0 1 2 3 4 5 6 7 8,A -1B 0C 0D 1E 1F 1 G 2 H 2 I 4,下标 data parent,树的双亲表示法实质上是一个静态链表.,5.2 树的存储结构孩子表示法,所谓孩子表示法是一种基于链表的存储方法。通常有两种形式

9、:,1. 多重链表表示法,其方法是:链表中的每个结点包括一个数据域和多个指针域,每个指针域指向该结点的一个孩子结点。,树中结点的度不同,那么如何设置指针域?,方案一,方案二,方案一: 指针域的个数等于该结点的度。,其中:data:数据域,存放该结点的数据信息;degree:度域,存放该结点的度;child1childd:指针域,指向该结点的孩子结点。,方案二:指针域的个数等于树的度。,其中:data:数据域,存放该结点的数据信息;child1childd:指针域,指向该结点的孩子结点。,方案一和方案二的优缺点?,0 1 2 3 4 5 6 7 8,空指针的数量为dn-(n-1)=n(d-1)+

10、1,2. 孩子链表表示法,所谓孩子链表表示法是把每个结点的孩子排列起来,看成是一个线性表,且以单链表存储,则n个结点共有n个孩子链表。而这n个单链表共有n个头指针,这n个头指针又组成了一个线性表,为了便于进行查找操作,可采用顺序存储。最后,将存放n个头指针的数组和存放n个结点的数组结合起来,构成孩子链表的表头数组。,孩子链表表示法中,存在两类结点:孩子结点和孩子链表的表头结点,如何设计呢?,(a) 孩子结点 (b) 表头结点,结 点 结 构,结 点 的 定 义,struct CTNode int child;CTNode *next; ; template struct CBNode T da

11、ta;CTNode *firstchild; ;,0 1 2 3 4 5 6 7 8,下标 data firstchild,A B C DE FG H I,5.2 树的存储结构双亲孩子表示法,0 1 2 3 4 5 6 7 8,A -1B 0C 0D 1 E 1F 1 G 2 H 2 I 4 ,下标 data parent firstchild,8,5.2 树的存储结构孩子兄弟表示法,该表示法又称为二叉链表表示法,其方法是链表中的每个结点除数据域外,还设置了两个分别指向该结点的第一个孩子和右兄弟的指针。,结点结构:,其中:data:数据域,存储该结点的数据信息; firstchild:指针域,

12、存储该结点第一个孩子结点地址; rightsib:指针域,存储该结点右兄弟结点的存储地址。,定义结点结构,template struct TNode T data;TNode *firstchild, *rightsib; ;,空指针的数量为2n+n-1=n+1, 问 题 ,根据以上存储结构,完成如下算法: 找出某结点的双亲、孩子、祖先和子孙; 前序、后序和层次遍历一棵树; 查找值为x的结点; 求某结点的度和层次,或整棵树的度和层数; 找出所有的叶子结点; 判断两棵树是否同构。,5.3 二叉树(binary tree )的逻辑结构,5.3.1 二叉树的定义,二叉树是n(n0)个结点的有限集合,

13、该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。,二叉树的特点:, 每个结点最多有两棵子树; 二叉树是有序的,其次序不能任意颠倒。,结论:二叉树和树是两种树结构。,二叉树具有5种基本形态:,几种特殊的二叉树,斜树 1 .所有结点都只有左子树的二叉树称为左斜树; 2 .所有结点都只有右子树的二叉树称为右斜树; 3.左斜树和右斜树统称为斜树。,1. 在斜树中,每一层只有一个结点; 2.斜树的结点个数与其深度相同。,满二叉树 在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上。,满二叉树的特点:, 叶子只能出

14、现在最下一层; 只有度为0和度为2的结点。,n个结点的满二叉树中有多少个叶子结点?有多少分支结点?,试证:非空满二叉树叶子结点的个数等于分支结点个数加1。,完全二叉树 对一棵具有n个结点的二叉树按层序编号,如果编号为i(1in)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同。,完全二叉树的特点:, 叶子结点只能出现在最下两层,且最下层的叶子结点都集中在二叉树的左部; 完全二叉树中如果有度为1的结点,只可能有一个,且该结点只有左孩子。,重要结论:一棵满二叉树必定是一棵完全二叉树。,5.3.2 二叉树的基本性质,性质5-1 二叉树的第i层上最多有2i-1个结点(i1)。,证明:

15、证明数学采用归纳法来证明。当i=1时,只有一个根结点,而2i-1=20 =1,结论显然成立。假定i=k(1ki时结论成立,即第k层上至多有2k-1个结点, 则 i=k+1时,因为第k+1层上的结点是第k层上结点的孩子,而二叉树中每个结点的度最大为2,故在第k+1层上最大结点个数为第k层上的最大结点个数的二倍,即22k-12k。所以当i=k+1时,至多有2k个结点,结论成立。由归纳法原理,命题成立。,性质5-2 一棵深度为k的二叉树中,最多有2 k1个结点,最少有k个结点。,证明:由性质1可知,深度为k的二叉树中最多结点个数= =2k-1;显然,具有2k1个结点的二叉树是满二叉树。 每一层至少要

16、有一个结点,因此深度为k的二叉树,至少有k个结点。,性质5-3 在一棵二叉树中,如果叶子结点数为n0,度为2的结点数为n2,则有: n0n21。,证明: 设n为二叉树的结点总数,n1为二叉树中度为1的结点数,因为二叉树中所有结点的度均小于或等于2,则有:nn0n1n2 ;二叉树,除了根结点外,其余结点都有唯一的一个分枝进入,因此,对于有n个结点的二叉树,其分枝数为n1。设B为二叉树中的分枝数,则有:nB1。由于这些分枝是由度为1和度为2的结点射出的,一个度为1的结点射出一个分枝,一个度为2的结点射出两个分枝,所以有:Bn12n2。于是得:nn12n21 ;因此可以得到:n0n21 。,性质5-

17、4 具有n个结点的完全二叉树的深度为 log2n+1 。,性质5-5 对一棵具有n个结点的完全二叉树中的结点从1开始按层序编号,则对于任意的序号为i(1in)的结点(简称为结点i),有: (1)如果i1,则结点i的双亲结点的序号为 i/2 ;如果i1,则结点i是根结点,无双亲结点。 (2)如果2in,则结点i的左孩子的序号为2i;如果2in,则结点i无左孩子。 (3)如果2i1n,则结点i的右孩子的序号为2i1;如果2i1n,则结点 i无右孩子。,5.3.3 二叉树的抽象数据类型定义,ADT BiTree Data二叉树是由一个根结点和两棵互不相交的左右子 树构成.二叉树中的结点具有相同数据类

18、型及层次关系. OperationInitBiTree前置条件:无输入:无功能:初始化一棵二叉树 输出:无后置条件:构造一个空的二叉树,DestroyBiTree 前置条件:二叉树已存在输入:无功能:销毁一棵二叉树输出:无后置条件:释放二叉树占用的存储空间 LeverOrder前置条件:二叉树已存在输入:无功能:层序遍历二叉树输出:二叉树中结点的一个线性排列后置条件:二叉树不变 endADT,5.3.4 二叉树的遍历操作,所谓遍历就是无重复无遗漏地访问。 二叉树的遍历是指按照某种次序访问二叉树中的所有结点,使得每个结点被访问一次且仅被访问一次。,二叉树遍历操作的结果?,非线性结构的遍历需要解决

19、的关键问题是什么?,二叉树的遍历方式有六种:DLR、LDR、LRD、DRL、RDL和RLD,如果限定先左后右,则二叉树遍历方式有三种:DLR、LDR、LRD,如果按二叉树的层序编号的次序访问各结点,则可得到另一种遍历次序:层序遍历。,1.前序(根)遍历 若二叉树为空,则空操作返回;否则: 访问根结点; 前序遍历根结点的左子树; 前序遍历根结点的右子树。,ABDGCEF,2.中序(根)遍历 若二叉树为空,则空操作返回;否则: 中序遍历根结点的左子树; 访问根结点; 中序遍历根结点的右子树。,DGBAECF,3.后序(根)遍历 若二叉树为空,则空操作返回;否则: 后序遍历根结点的左子树; 后序遍历

20、根结点的右子树。 访问根结点;,GDBEFCA,4.层序遍历 所谓二叉树的层次遍历,是指从二叉树的第一层(根结点)开始,从上至下逐层遍历,在同一层中,则按从左到右的顺序对结点逐个访问。,ABCDEFG,先序遍历:根(左子树)(右子树)。 中序遍历: (左子树)根(右子树)。 后序遍历: (左子树)(右子树)根。,先序遍历: A (B(D( G H)( )(C( E)( F( )( I) 中序遍历: (G )D( H) B( ) )A( E) C( ) F( I) 后序遍历: (G)( H) D) ( )B)( E)( ( )(I) F) C) A 层次遍历: A B C D E F G H I

21、,先序遍历:A B D G H C E F I 中序遍历: G D H B A E C F I 后序遍历: G H D B E I F C A 层次遍历:A B C D E F G H I,中序遍历的结果,先序遍历: 中序遍历: 后序遍历:,若已知一棵二叉树的的前序序列和中序序列,能否唯一确定这棵二叉树呢?怎样确定?,例如:已知一棵二叉树的前序遍历序列和中序遍历序列分别为A B C D E F G H I 和B C A E D G H F I,如何构造该二叉树呢?,前序:A B C D E F G H I中序:B C A E D G H F I,前序:A B C D E F G H I中序:B

22、 C A E D G H F I,前序:A B C D E F G H I中序:B C A E D G H F I,二叉树的构造算法思想:先根据前序序列的第一个元素建立根结点;然后在中序序列中找到该元素,确定根结点的左、右子树的中序序列;再在前序序列中确定左、右子树的前序序列;最后由左子树的前序序列与中序序列建立左子树,由右子树的前序序列与中序序列建立右子树。,5.4 二叉树的存储结构及实现,5.4.1 顺序存储结构,二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置(下标)应能体现结点之间的逻辑关系父子关系。,如何利用数组下标来反映结点之间的逻辑关系?,完全二叉树的顺序

23、存储,满二叉树的顺序存储,数组下标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15,一般二叉树的顺序存储,一棵斜树的顺序存储会怎样呢?,为什么会出现这种情况呢?,5.4.2 二叉链表,基本思想:令二叉树的每个结点对应一个链表结点,链表结点除了存放与二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。,结点结构:,其中,data:数据域,存放该结点的数据信息;lchild:左指针域,存放指向左孩子的指针,当左孩子不存在时为空指针;rchild:右指针域,存放指向右孩子的指针,当右孩子不存在时为空指针。,结点的类型描述:,template struct BiNode T

24、 data;BiNode *lchild, *rchild; ;,基于二叉链表存储结构的类声明,template class BiTree public:BiTree( )root=NULL; BiTree(BiNode *root); BiTree( ); void PreOrder(BiNode *root); void InOrder(BiNode *root); void PostOrder(BiNode *root); void LeverOrder(BiNode *root); private:BiNode *root; void Creat(BiNode *root); void

25、 Release(BiNode *root);,1前序遍历递归算法,template Void BiTree:PreOrder(BiNode *root) if (root =NULL) return; else coutdata; PreOrder(root-lchild); PreOrder(root-rchild); ,6,7,3,5,A,G,B,C,D,F,E,4,2,1,访问结点序列:,A,栈S内容:,A,D,B,B,D,G,C,E,F,G,C,E,F,前序遍历的非递归实现,二叉树前序遍历的非递归算法的关键是:在前序遍历过某结点的整个左子树后,如何找到该结点的右子树的根指针。 解决办

26、法是在访问完该结点后,将该结点的指针保存在栈s中,以便以后能通过它找到该结点的右子树。,在前序遍历中,设要遍历二叉树的根指针为root,则有两种可能: 若root!=NULL,则表明?如何处理? 若root=NULL,则表明?如何处理?,栈s初始化; 循环直到root为空且栈s为空 当root不空时循环输出rootdata; 将指针root的值保存到栈中; 继续遍历root的左子树 如果栈s不空,则将栈顶元素弹出至root;准备遍历root的右子树;,前序遍历的非递归算法,template void BiTree:PreOrder(BiNode *root) top= -1; p=root;

27、/采用顺序栈s,并假定不会发生上溢while (p!=NULL | | top!= -1) while (p!= NULL) /找此结点的最左边的后代 coutdata; /访问s+top=p; /此结点进栈p=p-lchild; /转移到左儿子子树if (top!= -1) p=stop-; p=p-rchild; ,前序遍历的非递归算法,前序遍历二叉树的非递归算法2,template void BiTree:PreOrder2(BiNode *root) If(root!=NULL) top=0; stop=root; while(top!=-1) p=stop-; /出栈coutdata

28、; /访问if (p-rchild) s+top=p-rchild; /p的右儿子进栈;if (p-lchild) s+top=p-lchild; /p的左儿子进栈; / whilereturn OK;/ if / PreOrder2.,template void BiTree:PreOrder3(BiNode *root) If(root!=NULL) top=-1; p=root; while(top!=-1|p!=NULL) while(!p) coutdata; /访问 if (p-rchild) s+top=p-rchild; /只有右儿子进栈; p=p-lchild; / whil

29、e if(top!=-1)p=stop- /while return OK; / if / PreOrder3.,前序遍历二叉树的非递归算法3,2中序遍历递归算法,template void BiTree:InOrder (BiNode *root) if (root=NULL) return; else InOrder(root-lchild); coutdata; InOrder(root-rchild); ,非递归算法,template void BiTree:InOrder1(BiNode *root) top= -1; /采用顺序栈s,并假定不会发生上溢while (root!=NU

30、LL | | top!= -1) while (root!= NULL) /找此结点的最左边的后代 s+top=root; /此结点进栈root=root-lchild; /转移到左儿子子树 #2 whileif (top!= -1) root=stop-; coutdata; /访问root=root-rchild; /#1 while ,中序遍历的非递归算法1,template void BiTree:InOrder2(BiNode *root) top=0; stop=root; while (top!= -1) p=stop; while (p) /找此结点的最左边的后代p=p-lch

31、ild; /转移到左儿子子树s+top=p; /此结点进栈 #2 whiletop=top-1; if (top!= -1) p=stop-; coutdata; stop+=p-rchild; /#1 while ,中序遍历的非递归算法2,template void BiTree:InOrder3(BiNode *root) top=-1; p=root; while (p|top!= -1) if(p)/根进栈,遍历左儿子s+top=p; p=p-lchild; else p=stop-; coutdata; /输出p=p-rchild; /#1 while ,中序遍历的非递归算法3,3后

32、序遍历递归算法,template void BiTree:PostOrder(BiNode *root) if (root=NULL) return; else PostOrder(root-lchild); PostOrder(root-rchild); coutdata; ,非递归算法,后序遍历的非递归算法,template void BiTree:PostOrder(BiNode *root) top= -1; /采用顺序栈,并假定栈不会发生上溢 while (root!=NULL | | top!= -1) while (root!=NULL) top+; stop.ptr=root;

33、stop.flag=1; root=root-lchild; while (top!= -1 ,Status PostOrderTraverse(BiTree root, Status( * Visit)(TElemType e) /后序遍历二叉树的非递归算法2。S为栈,top为栈顶指针。 / InitStack,StackEmpty,push,pop为栈操作, Visit为访问结点的函数 p=root; InitStack(S); while(!StackEmpty(S)| p!=NULL) while(!p) push(S,p); if (p-lchild!=NULL) p=p-lchil

34、d;elsep=p-rchild; Pop(S, p);if(!Visit(p-data) return ERROR; / coutdata 访问p. while(!StackEmpty(S) / while / PostOrderTraverse.,Status PostOrderTraverse_3(BiTree T, Status( * Visit)(TElemType e) /后序遍历二叉树的非递归算法3。S为栈,top为栈顶指针。 / InitStack,StackEmpty,push,pop为栈操作, Visit为访问结点的函数; t=T; InitStack(S); flag=-

35、1; do while(t!=NULL) push(S,t); t=t-lchild; p=NULL; flag=1;while(!StackEmpty(S) / PostOrderTraverse_3.,4层序遍历,队列Q初始化; 2. 如果二叉树非空,将根指针入队; 3. 循环直到队列Q为空3.1 q=队列Q的队头元素出队;3.2 访问结点q的数据域;3.3 若结点q存在左孩子,则将左孩子指针入队;3.4 若结点q存在右孩子,则将右孩子指针入队;,template void BiTree:LeverOrder(BiNode *root) front=rear=0; /采用顺序队列,并假定不

36、会发生上溢 if (root=NULL) return; Q+rear=root; while (front!=rear) q=Q+front; coutdata; if (q-lchild!=NULL) Q+rear=q-lchild; if (q-rchild!=NULL) Q+rear=q-rchild; ,5二叉树的建立,为了建立一棵二叉树,我们将二叉树做如下处理:将二叉树中每个结点的空指针引出一个虚结点,其值为一特定值如“#”,以标识其为空,把这样处理后的二叉树称为原二叉树的扩展二叉树。,为什么做如此处理呢?,扩展二叉树的前序遍历序列:AB#D#C#,设二叉树中的结点均为一个字符。假

37、设扩展二叉树的前序遍历序列由键盘输入,root为指向根结点的指针,二叉链表的建立过程是: 首先输入根结点,若输入的是一个“#”字符,则表明该二叉树为空树,即root=NULL;否则输入的字符应该赋给root-data,,之后依次递归建立它的左子树和右子树 。,template BiTree :BiTree(BiNode *root) creat(root); void BiTree :Creat(BiNode *root) cinch;if (ch=# ) root=NULL; else root=new BiNode; root-data=ch;Creat(root-lchild); Cre

38、at(root-rchild); ,建立二叉递归算法,5.4.3 三叉链表,对二叉链表的一种改进,在二叉链表的基础上增加了一个指向双亲的指针域。,结点结构:,其中:data、lchild和rchild三个域的含义同二叉链表的结点结构; parent域为指向该结点的双亲结点的指针。,5.4.4 线索链表,二叉链表的那些空指针域中指向前驱结点和后继结点的指针被称为线索(thread),使二叉链表中结点的空链域存放其前驱或后继信息的过程称为线索化,加上线索的二叉树称为线索二叉树。,线索链表中结点定义:,enum flag Child, Thread; Template struct ThrNode

39、T data;ThrNode *lchild, *rchild;flag ltag, rtag; ;,中序线索链表类的声明,template class InThrBiTree public:InThrBiTree(ThrNode * root); InThrBiTree( ); ThrNode *Next(ThrNode *p); void InOrder(ThrNode *root); private:ThrNode *root; void Creat(ThrNode *root); void ThrBiTree(ThrNode *root); ;,二叉树的遍历方式有4种,故有4种意义下的

40、前驱和后继,相应的有4种线索二叉树: 前序线索二叉树; 中序线索二叉树; 后序线索二叉树; 层序线索二叉树。,例:中序线索二叉树的示意图,1中序线索链表的建立(构造函数),分析:建立线索链表,实质上就是将二叉链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历该二叉树时才能得到。因此,建立线索链表首先要建立二叉链表,然后在遍历的过程中修改空指针。,在遍历过程中,访问当前结点root的操作为: 结点root的左、右指针域,如果为空,则将相应标志置1; 若左指针域为空,则可令其指向它的前驱;因root的后继尚未访问到,所以它的右指针域要等到下次访问才能进行。为实现这一过程,设指针p

41、re始终指向刚刚访问过的结点,即若指针root指向当前结点,则pre指向它的前驱,显然pre的初值为NULL; 令pre=root,即令pre指向刚刚访问过的结点root;,1. 建立二叉链表,将每个结点的左右标志置为0; 2. 遍历二叉链表,建立线索;2.1 如果二叉链表root为空,则空操作返回;2.2 对root的左子树建立线索;2.3 对根结点root建立线索;2.3.1 若root没有左孩子,则为root加上前驱线索;2.3.2 若root没有右孩子,则将root右标志置为1;2.3.3 若结点pre右标志为1,则为其加上后继线索;2.3.4 令pre指向刚刚访问的结点;2.4 对r

42、oot的右子树建立线索。,中序线索链表的建立的伪代码,左图所示存储结构你想到什么?,答案一,答案一,树和二叉树之间如何转换?,分析物理结构和逻辑结构?,5.5 树、森林与二叉树的转换,1.树转换为二叉树,加线树中所有相邻兄弟之间加一条连线。 去线对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其它孩子结点之间的连线。 层次调整以根结点为轴心,将树顺时针转动一定的角度,使之层次分明。,ABEFCDG,ABEFCDG,树的前序遍历等价于二叉树的前序遍历!,EFBCGDA,EFBCGDA,树的后序遍历等价于二叉树的中序遍历!,2森林转换为二叉树, 将森林中的每棵树转换成二叉树; 从第二

43、棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。,1,2,3二叉树转换为树或森林, 加线若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、,都与结点y用线连起来; 去线删去原二叉树中所有的双亲结点与右孩子结点的连线; 层次调整整理由、两步所得到的树或森林,使之层次分明。,加线,去线,层次调整,根结点,根结点的最大的孩子,根结点最大的弟弟,树或森林变成二叉树后的结点情况,4. 森林的遍历,森林有两种遍历方法: 前序(根)遍历:前序遍历森林即为前序遍历森林中的每一棵树。(=二叉树的前序(根)

44、遍历) 后序(根)遍历:后序遍历森林即为后序遍历森林中的每一棵树。(=二叉树的中序(根)遍历),5.6.1 二叉树的应用举例哈夫曼树及哈夫曼编码,1. 哈夫曼树(Huffman tree)相关概念,叶子结点的权值对叶子结点赋予的一个有意义的数值量。,二叉树的带权路径长度设二叉树具有n个带权值的叶子结点,从根结点到各个叶子结点的路径长度与相应叶子结点权值的乘积之和。 记为:,WPL=,其中:wk为第k个叶子结点的权值;lk为从根结点到第k个叶子结点的路径长度。,哈夫曼树 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权路径长度最小的二叉树。,例:给定4个叶子结点,其权值分别为2

45、,3,4,5,可以构造出形状不同的多个二叉树。,图5-36 一个带权二叉树, WPL=28,哈夫曼算法基本思想: 初始化:由给定的n个权值w1,w2,wn构造n棵只有一个根结点的二叉树,从而得到一个二叉树集合FT1,T2,Tn; 选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子树构造一棵新的二叉树,这棵新二叉树的根结点的权值为其左、右子树根结点的权值之和; 删除与加入:在F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到F中; 重复、两步,当集合F中只剩下一棵二叉树时,这棵二叉树便是哈夫曼树。,下面给出叶子结点的权值集合为W2,3,4,5的哈夫曼树的构造过程。,(c

46、) 第三步,1 初始化,2 选取与合并,给出叶子结点的权值集合为W=5,2,9,11, 8,3,7的哈夫曼树的构造过程。,3 删除与加入,4 重复2 、3 两步,4 重复2 、3 两步,4 重复2 、3 两步,4 重复2 、3 两步,哈夫曼算法的存储结构,struct element int weight;int lchild, rchild, parent; ;,伪代码,1. 数组huffTree初始化,所有元素结点的双亲、左右孩子都置为-1;2. 数组huffTree的前n个元素的权值置给定权值wn;3. 进行n-1次合并3.1 在二叉树集合中选取两个权值最小的根结点,其下标分别为i1, i2;3.2 将二叉树i1、i2合并为一棵新的二叉树k;,5,6,weight parent lchild rchild,6 -1 -1 -1 5 -1 -1 -1 2 -1 -1 -1 4 -1 -1 -1-1 -1 -1-1 -1 -1-1 -1 -1,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报