




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第六章第六章树和二叉树树和二叉树26.1 树的类型定义树的类型定义6.2 6.2 二叉树的类型定义二叉树的类型定义6.3 二叉树的存储结构二叉树的存储结构6.4 二叉树的遍历二叉树的遍历6.5 线索二叉树线索二叉树6.6 树和森林的表示方法树和森林的表示方法6.7 树和森林的遍历树和森林的遍历6.8 哈夫曼树与哈夫曼编码哈夫曼树与哈夫曼编码36.1 树的类型定义树的类型定义4数据对象数据对象 D:D是具有相同特性的数据元素的集合。是具有相同特性的数据元素的集合。 若若D为空集,则称为空树为空集,则称为空树 。 否则否则: (1) 在在D中存在唯一的称为根的数据元素中存在唯一的称为根的数据元素
2、root; (2) 当当n1时,其余结点可分为时,其余结点可分为m (m0)个互个互 不相交的有限集不相交的有限集T1, T2, , Tm,其中每一,其中每一 个子集本身又是一棵符合本定义的树,个子集本身又是一棵符合本定义的树, 称为根称为根root的子树。的子树。 数据关系数据关系 R:5 基本操作:基本操作:查查 找找 类类 插插 入入 类类删删 除除 类类6 Root(T) / 求树的根结点求树的根结点 查找类:查找类:Value(T, cur_e) / 求求cur_e结点的元素值结点的元素值 Parent(T, cur_e) / 求求cur_e结点的双亲结点结点的双亲结点LeftChi
3、ld(T, cur_e) / 求求cur_e结点的最左孩子结点的最左孩子 RightSibling(T, cur_e) / 求求cur_e结点的右兄弟结点的右兄弟TreeEmpty(T) / 判定树是否为空树判定树是否为空树 TreeDepth(T) / 求树的深度求树的深度TraverseTree( T, Visit() ) / 遍历遍历7InitTree(&T) / 初始化置空树初始化置空树 插入类:插入类:CreateTree(&T, definition) / 按定义构造树按定义构造树Assign(T, &cur_e, value) / 给给cur_e结点赋值结
4、点赋值InsertChild(&T, &p, i, c) /插入插入c为为T中中P所指结点的第所指结点的第i棵子树棵子树8 ClearTree(&T) / 将树清空将树清空 删除类:删除类:DestroyTree(&T) / 销毁树的结构销毁树的结构DeleteChild(&T, &p, i) / 删除结点删除结点p的第的第i棵子树棵子树9ABCDEFGHIJMKLA( B(E, F(K, L), C(G), D(H, I, J(M) )T1T3T2树根例如例如: :树的图示表示法树的广义表表示法10ABDCJIHMEFGKL树的嵌套集合表示法1
5、1() 有确定的根;() 树根和子树根之间为有向关系。有向树有向树:有序树:有序树:子树之间存在确定的次序关系。无序树:无序树:子树之间不存在确定的次序关系。12基基 本本 术术 语语13结点结点: :结点的度结点的度: :树的度树的度: :叶子结点叶子结点: :分支结点分支结点: :数据元素+ +若干指向子树的分支分支的个数(子树的个数)树中所有结点的度的最大值度为零的结点度大于零的结点包含根结点和中间结点DHIJM14(从根到结点的)路径路径:孩子孩子结点、双亲双亲结点兄弟兄弟结点、堂兄弟堂兄弟祖先祖先结点、子孙子孙结点结点的层次结点的层次: :树的深度:树的深度: 由从根根到该结点所经分
6、支和结点构成ABCDEFGHIJMKL假设根结点的层次为1,根的孩子为第2层,如果某结点在第L层,则其子树的根在L+1层。树中叶子结点所在的最大层次15任何一棵非空树是一个二元组 Tree = (root,F)其中:root 被称为根结点 F 被称为子树森林森林:森林:是m(m0)棵互不相交的树的集合ArootBCDEFGHIJMKLF16对比对比树型结构树型结构和和线性结构线性结构的结构特点的结构特点17线性结构线性结构 树型结构树型结构 (非线性结构)(非线性结构)第一个数据元素第一个数据元素 ( (无前驱无前驱) ) 根结点根结点 ( (无前驱无前驱) )最后一个数据元素最后一个数据元素
7、 (无后继无后继)多个叶子多个叶子结点结点 ( (无后继无后继) )其它数据元素其它数据元素( (一个前驱、一个前驱、 一个后继一个后继) )其它数据元素其它数据元素( (一个前驱、一个前驱、 多个后继多个后继) )18赵老根赵老根赵跃进赵跃进赵小康赵小康赵改革赵改革赵开放赵开放赵抗美赵抗美赵援朝赵援朝赵卫兵赵卫兵赵永红赵永红196.2 二叉树的类型定义二叉树的类型定义20 二叉树或为空树空树,或是由一个根结点根结点加上两棵两棵分别称为左子树左子树和右子树的、互不交的互不交的二叉树二叉树组成。(二叉树的度最大为2)ABCDEFGHK根结点左子树右子树21二叉树的五种基本形态:二叉树的五种基本形
8、态:N空树空树只含根结点只含根结点NNNLRR右子树为空树右子树为空树L左子树为空树左子树为空树左右子左右子树均不树均不为空树为空树22 二叉树的主要基本操作二叉树的主要基本操作:查查 找找 类类插插 入入 类类删删 除除 类类23 Root(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(); InOrderTrave
9、rse(T, Visit(); PostOrderTraverse(T, Visit(); LevelOrderTraverse(T, Visit();24 InitBiTree(&T); Assign(T, &e, value); CreateBiTree(&T, definition); InsertChild(T, p, LR, c);25ClearBiTree(&T); DestroyBiTree(&T);DeleteChild(T, p, LR);2627性质1:二叉树第 i 层上至多有2i-1 个结点。 (i1)用归纳法证明用归纳法证明: 归
10、纳基归纳基: 归纳假设:归纳假设: 归纳证明:归纳证明:i = 1层时,只有一个根结点:层时,只有一个根结点: 2i-1 = 20 = 1;假设当假设当j=i-1时时,命题成立;命题成立;即即 j层最多有层最多有2j-1(2i-2) 个节点个节点二叉树上每个结点至多有两棵子树,二叉树上每个结点至多有两棵子树,则第则第 i 层的结点数层的结点数 = 2i-2 2 = 2i-1。28性质 2 : 深度为 k 的二叉树上至多含 2k-1 个结点(k1)。证明:证明: 基于上一条性质,深度为基于上一条性质,深度为 k 的二叉的二叉树上的结点数至多为树上的结点数至多为 20+21+ +2k-1 = 2k
11、-1 。 (等比数列求和)(等比数列求和)29 性质 3 : 对任何一棵二叉树,若它含有n0 个叶子结点(0度节点)、n2 个度为 2 的结点,则必存在关系式:n0 = n2+1。证明:证明:二叉树上结点总数二叉树上结点总数 n = n0 + n1 + n2又又 二叉树上分支总数二叉树上分支总数 b = n1+2n2 而而 b = n-1 = n0 + n1 + n2 - 1由此,由此, n0 = n2 + 1 。30两类两类特殊特殊的二叉树:的二叉树:满二叉树:满二叉树:指的是深度为指的是深度为k且且含有含有2k-1个结点的二叉树。个结点的二叉树。完全二叉树完全二叉树:树中所含的树中所含的
12、n 个结点和满二叉树中个结点和满二叉树中编编号为号为 1 至至 n 的结点的结点一一对一一对应。(编号的规则为,由应。(编号的规则为,由上到下,从左到右。)上到下,从左到右。)123456789 10 11 12 13 14 15abcdefghij特点特点 1. 叶子结点出现在最后叶子结点出现在最后2层层 2. 对于任意结点,若其右对于任意结点,若其右 分支下的子孙的最大层次为分支下的子孙的最大层次为L, 则左分支下的子孙的最大层次则左分支下的子孙的最大层次 为为L或或L+131 性质性质 4 :具有具有 n 个结点的完全二个结点的完全二叉树的叉树的深度深度为为 log2n +1 (k1)证
13、明:证明:设完全二叉树的深度为设完全二叉树的深度为 k 则根据第二条性质得则根据第二条性质得 2k-1-1 n 2k-1 即即 k -1 log2 n data); / 访问根结点访问根结点 PreOrder (T-lchild, visit); / 遍历左子树遍历左子树 PreOrder (T-rchild, visit);/ 遍历右子树遍历右子树 ADB T 53void InOrder (BiTree T, void(*Visit)(TElemType) / 中序遍历二叉树中序遍历二叉树 if (T) InOrder (T-lchild, visit); / 遍历左子树遍历左子树 vis
14、it(T-data); / 访问根结点访问根结点 InOrder (T-rchild, visit);/ 遍历右子树遍历右子树 54void PostOrder (BiTree T, void(*Visit)(TElemType) / 后序遍历二叉树后序遍历二叉树 if (T) PostOrder (T-lchild, visit); / 遍历左子树遍历左子树 PostOrder(T-rchild, visit);/ 遍历右子树遍历右子树 visit(T-data); / 访问根结点访问根结点 55 可以这样理解:无论先序、中序、后序可以这样理解:无论先序、中序、后序遍历二叉树,遍历时的搜索路
15、线是相同的:遍历二叉树,遍历时的搜索路线是相同的:从根结点出发,逆时针沿二叉树外缘移动对从根结点出发,逆时针沿二叉树外缘移动对每个结点均途经三次。每个结点均途经三次。 先序遍历:第一次经过结点时访问。先序遍历:第一次经过结点时访问。 中序遍历:第二次经过结点时访问。中序遍历:第二次经过结点时访问。 后序遍历:第三次经过结点时访问。后序遍历:第三次经过结点时访问。AB12356四、先序遍历算法的非递归描述四、先序遍历算法的非递归描述 1.初始化设置一个栈;初始化设置一个栈; 2.根结点指针入栈;根结点指针入栈; 3.堆栈非空时:堆栈非空时: (1)出栈取得结点指针,)出栈取得结点指针,visit
16、 该结点该结点 (2)若该结点右子树不空,右子树指针进栈;)若该结点右子树不空,右子树指针进栈; (3)若该结点左子树不空,左子树指针进栈;)若该结点左子树不空,左子树指针进栈;57void void pre_s(BiTreepre_s(BiTree t) t) SqStackSqStack s; s; BiTreeBiTree p; p; Init_Sq(sInit_Sq(s);); if(tif(t) ) push(s,tpush(s,t);); while(!StackEmpty(swhile(!StackEmpty(s) pop(s,ppop(s,p);); printf(%dprin
17、tf(%d ,p-data); ,p-data); if(pif(p-rchildrchild) ) push(s,ppush(s,p-rchildrchild);); if(pif(p-lchildlchild) ) push(s,ppush(s,p-lchildlchild);); 58五、中序遍历算法的非递归描述五、中序遍历算法的非递归描述void GoFarLeft(BiTree bt,BiTree &p) if(bt) p=bt; while(p-lchild ) push(s, p); p = p-lchild; /得到树得到树T最左结点的指针最左结点的指针59void i
18、n_s(BiTree t) BiTree p=t; Init_Sq(s); GoFarLeft(t, p); / 找到最左的结点找到最左的结点 while(p) printf(%d ,p-data); if(p-rchild ) GoFarLeft(p-rchild,p); else if ( !StackEmpty(s) / 栈不空时退栈栈不空时退栈 pop(s,p); else p= NULL; / 栈空表明遍历结束栈空表明遍历结束 / while 60遍历算法的应用举例遍历算法的应用举例1、建立二叉树的存储结构、建立二叉树的存储结构3、求二叉树的深度、求二叉树的深度(后序遍历后序遍历)2
19、、统计二叉树中叶子结点的个数、统计二叉树中叶子结点的个数 6162 以字符串的形式以字符串的形式 根根 左子树左子树 右子树右子树定义一棵二叉树定义一棵二叉树例如:ABCD以字符“ # ”表示A(B( #,C(# , #),D(#, # )空树空树只含一个根结点只含一个根结点的二叉树的二叉树A以字符串“A # # ”表示以下列字符串表示63void CreateBiTree(BiTree &bt) /*以扩展的先序序列输入数据以扩展的先序序列输入数据*/ char ch; scanf(%c,&ch); if(ch=#) bt=NULL; else bt=(BiTree)mall
20、oc(sizeof(BiTNode); if(!bt) exit(1); bt-data=ch; CreateBiTree(bt-lchild); CreateBiTree(bt-rchild); 64A B C D A BCD上页算法执行过程举例如下:ATBCD652、统计二叉树中叶子结点的个数、统计二叉树中叶子结点的个数算法基本思想算法基本思想: :遍历二叉树,在遍历过程中查找叶子结点,并计数。由此,需在遍历算法中增添一个需在遍历算法中增添一个“计数计数”的参数,的参数,并将算法中“访问结点”的操作改为:若是叶子,则计数器增若是叶子,则计数器增1 1。663、求二叉树的深度、求二叉树的深度
21、(后序遍历后序遍历)算法基本思想算法基本思想: : 从二叉树深度的定义可知,二叉树的深二叉树的深度应为其左、右子树深度的最大值加度应为其左、右子树深度的最大值加1 1。由此,需先分别求得左、右子树的深度,需先分别求得左、右子树的深度,算法中“访问结点”的操作为:求得左、右求得左、右子树深度的最大值,然后加子树深度的最大值,然后加 1 1 。 首先分析二叉树的深度二叉树的深度和它的左左、右子右子树深度树深度之间的关系。67int depthval,depthLeft,depthRight;int Depth(BiTree T )/ 返回二叉树的深度返回二叉树的深度, T为树根的指针为树根的指针
22、if ( !T ) depthval = 0; else depthLeft = Depth( T-lchild); depthRight= Depth( T-rchild ); depthval = 1 + (depthLeft depthRight ? depthLeft : depthRight); return depthval;68例例1. 已知树的先序次序为已知树的先序次序为 abdcegf 中序次序为中序次序为 bdaegcf 则树为?则树为?abdcfeg例例2. 已知树的后序次序为已知树的后序次序为 dbgefca 中序次序为中序次序为 bdaegcf 则树为?则树为?我们可
23、以利用我们可以利用先序次序和中序次序、后先序次序和中序次序、后序次序和中序次序序次序和中序次序 来确定一棵二叉树来确定一棵二叉树。69 何谓线索二叉树? 线索链表的遍历算法 如何建立线索链表?70一、一、何谓线索二叉树?何谓线索二叉树?遍历二叉树的结果是, 求得结点的一个线性序列。ABCDEFGHK例如:先序先序序列: A B C D E F G H K中序中序序列: B D C A H G K F E后序后序序列: D C B H K G F E A71指向该线性序列中的“前驱”和 “后继” 的指针指针,称作“线索线索”与其相应的二叉树,称作 “线索二叉树线索二叉树”包含 “线索” 的存储结
24、构,称作 “线索链线索链表表”A B C D E F G H K D C B E 72例例 求如下二叉树的先序线索树、中序线索树和后序线索树。求如下二叉树的先序线索树、中序线索树和后序线索树。ABCDABCDABCDABCD先序线索树先序线索树 中序线索树中序线索树 后序线索树后序线索树 abcd bcad cbdaNULLNULLNULLNULLNULL73如何保存这种在遍历过程中得到的信息?最简单的如何保存这种在遍历过程中得到的信息?最简单的方法是在每个结点上方法是在每个结点上增加二个指针域增加二个指针域:fwd和和bkwd用来指示此结点在遍历中的前驱和后继结点。用来指示此结点在遍历中的前
25、驱和后继结点。这样,使结点的存储密度大大降低。这样,使结点的存储密度大大降低。我们知道在我们知道在n个个结点的二叉树中,有结点的二叉树中,有n+1个空链域个空链域。(空链域的个数空链域的个数=结点数结点数*2 分支个数)分支个数) n结点二叉树的空链域结点二叉树的空链域=2*n- (n-1)=n+1我们可以利用这我们可以利用这n+1个空链域来存储线索个空链域来存储线索。74对对线索链表线索链表中结点的约定:中结点的约定: 在二叉链表的结点中增加两个标志域,在二叉链表的结点中增加两个标志域,并作如下规定:并作如下规定:若该结点的左子树不空,若该结点的左子树不空,则则Lchild域的指针指向其左子
26、树,域的指针指向其左子树, 且左标志域的值为且左标志域的值为“Link(指针)(指针)”; 否则,否则,Lchild域的指针指向其域的指针指向其“前驱前驱”, 且左标志的值为且左标志的值为“Thread(线索)(线索) ” 。75若该结点的右子树不空,若该结点的右子树不空,则rchild域的指针指向其右子树, 且右标志域的值为 “Link(指针)”;否则,rchild域的指针指向其“后继”, 且右标志的值为“Thread(线索) ”。 如此定义的二叉树的存储结构称作如此定义的二叉树的存储结构称作“线索链表线索链表”。76typedef struct BiThrNod TElemType dat
27、a; struct BiThrNode *lchild, *rchild; / 左右指针 PointerThr LTag, RTag; / 左右标志 BiThrNode, *BiThrTree;线索链表的类型描述: #define Link 0 /指针 #define Thread 1 /线索 typedef enum Link, Thread PointerThr; 77要求:已知一个二叉树,我们要会画出它的各种线索树。要求:已知一个二叉树,我们要会画出它的各种线索树。ABCDEFGHK画出它的先序线索树、中序线索树、后序线索树?78ABCDEFGHK先序线索树先序线索树A B C D E
28、F G H KNULL79ABCDEFGHK中序线索树中序线索树B D C A H G K F ENULLNULL80ABCDEFGHK后序线索树后序线索树D C B H K G F E ANULL81二、线索链表的遍历算法二、线索链表的遍历算法:对于增加二个指针域的结构:对于增加二个指针域的结构:for ( p = firstNode(T); p; p = Succ(p) ) Visit (p);由于在线索链表中添加了遍历中得到的“前驱”和“后继”的信息,从而简化了遍历的算法。82例如例如: (对于利用空指针域的结构)(对于利用空指针域的结构) /中序线索化链表的遍历算法中序线索化链表的遍历
29、算法 中序遍历的第一个结点中序遍历的第一个结点 ? 在中序线索化链表中结点的后继在中序线索化链表中结点的后继 ?左子树上处于“最左最左”(没有左子树)的结点。若若无右子树,则为则为后继线索后继线索所指结点;否则为否则为对其右子树右子树进行中序遍历遍历时访问的第一个结点。第一个结点。83void InOrderTraverse_Thr(BiThrTree T, Status (*Visit)(TElemType ) p = T-lchild; / p指向根结点,T指向二叉线索树的头结点 while (p != T) / 空树或遍历结束时,p=T while (p-LTag= =Link) p =
30、 p-lchild; / 第一个结点 if (!visit(p-data) return ERROR; while (p-RTag= =Thread & p-rchild!=T) / 访问后继结点 p = p-rchild; Visit(p-data); p = p-rchild; / p进至其右子树根 / InOrderTraverse_Thr84 在中序遍历过程中修改结点的在中序遍历过程中修改结点的左、右指针域,以保存当前访问结左、右指针域,以保存当前访问结点的点的“前驱前驱”和和“后继后继”信息。遍信息。遍历过程中,附设指针历过程中,附设指针pre, 并始终保并始终保持指针持指针
31、p所指结点是当前访问的结点,所指结点是当前访问的结点, pre指向指向p结点的前驱。结点的前驱。三、如何建立线索链表?三、如何建立线索链表?85/ 已知一棵二叉树,将其中序线索化已知一棵二叉树,将其中序线索化/ pre指向 p 的前驱,第一次值为NULLvoid InThreading(BiThrTree p) if (p) / 对以p为根的非空二叉树进行线索化 InThreading(p-lchild); / 左子树线索化 if (!p-lchild) / 建前驱线索 p-LTag = Thread; p-lchild = pre; if (!pre-rchild) / 建后继线索 pre-
32、RTag = Thread; pre-rchild = p; pre = p; / 保持 pre 指向 p 的前驱 InThreading(p-rchild); / 右子树线索化 / if / InThreading86ABCDif (A) /InThreading(A) ,pre=NULL InThreading(A-lchild); / 左子树线索化 if (!A-lchild) / 建前驱线索 ,pre=C A-LTag = Thread; A-lchild = pre; if (!pre-rchild) / 建后继线索 pre-RTag = Thread; pre-rchild = A
33、; pre = A; / 保持 pre 指向 p 的前驱 InThreading(A-rchild); if (B) /InThreading(B) ,pre=NULL InThreading(B-lchild); / 左子树线索化 if (!B-lchild) / 建前驱线索 B-LTag = Thread; B-lchild = pre; if (!pre-rchild) / 建后继线索 pre-RTag = Thread; pre-rchild = B; pre = B; / 保持 pre 指向 p 的前驱 InThreading(B-rchild); ABCDNULL87if (C)
34、/InThreading(C) ,pre=B InThreading(C-lchild); / 左子树线索化 if (!C-lchild) / 建前驱线索 C-LTag = Thread; C-lchild = B; if (!B-rchild) / 建后继线索 B-RTag = Thread; B-rchild = C; pre = C; / 保持 pre 指向 p 的前驱 InThreading(C-rchild); /pre=Cif (D) /InThreading(D) ,pre=A InThreading(D-lchild); / 左子树线索化 if (!D-lchild) / 建前
35、驱线索 D-LTag = Thread; D-lchild = A; if (!A-rchild) / 建后继线索 A-RTag = Thread; A-rchild = D; pre = D; / 保持 pre 指向 p 的前驱 InThreading(D-rchild); ABCDABCD88Status InOrderThreading(BiThrTree &Thrt, BiThrTree T) / 构建中序线索链表 if (!(Thrt = (BiThrTree)malloc( sizeof( BiThrNode) exit (OVERFLOW); Thrt-LTag = Li
36、nk; Thrt-RTag =Thread; Thrt-rchild = Thrt; / 添加头结点 return OK; / InOrderThreading 89if (!T) Thrt-lchild = Thrt; else Thrt-lchild = T; pre = Thrt; InThreading(T); pre-rchild = Thrt; / 处理最后一个结点 pre-RTag = Thread; Thrt-rchild=pre;90 6.6 树和森林树和森林 的表示方法的表示方法91树的三种存储结构树的三种存储结构一、一、双亲表示法双亲表示法二、二、孩子链表表示法孩子链表表
37、示法三、三、树的二叉链表树的二叉链表( (孩子孩子- -兄弟)兄弟) 存储表示法存储表示法92ABCDEFG0 A -11 B 02 C 03 D 04 E 2 5 F 26 G 5r=0n=7data parent一、双亲表示法一、双亲表示法:93 typedef struct PTNode TElemType data; int parent; / 双亲位置域 PTNode; data parent#define MAX_TREE_SIZE 100结点结构结点结构:C语言的类型描述语言的类型描述: :94typedef struct PTNode nodesMAX_TREE_SIZE; i
38、nt r, n; / 根结点的位置和结点个数 PTree;树结构树结构:95ABCDEFG0 A1 B 2 C 3 D 4 E 5 F 6 G r=0n=7 data firstchild 1 2 34 56二、孩子链表表示法二、孩子链表表示法:-100022496typedef struct CTNode int child; /不是TElemType struct CTNode *next; *ChildPtr;孩子结点结构孩子结点结构: child nextC语言的类型描述语言的类型描述: :97 typedef struct TElemType data; int parent; Ch
39、ildPtr firstchild; / 孩子链表的头指针 CTBox;表结点结构表结点结构 data firstchildparent98typedef struct CTBox nodesMAX_TREE_SIZE; int n, r; / 结点数和根结点的位置 CTree;树结构树结构:99ABCDEFG AB C E D F Groot AB C E D F G 三、树的二叉链表三、树的二叉链表 (孩子孩子-兄弟)存储表示法兄弟)存储表示法100要求要求 将一棵树转化为二叉树将一棵树转化为二叉树 ABCDEFGHIJKLABCDEFKLGHIJ101typedef struct CSN
40、ode TElemType data; struct CSNode *firstchild, *nextsibling; CSNode, *CSTree;C语言的类型描述语言的类型描述: :结点结构结点结构: firstchild data nextsibling102 森林和二叉树的对应关系森林和二叉树的对应关系设设森林森林 F = ( T1, T2, , Tn ); T1 = (root,t11, t12, , t1m);二叉树二叉树 B =( LBT, Node(root), RBT );103。T1T2T3T4TnT1T11T12T1m。T1T11T12T1m。T2T3Tn。104由森
41、林转换成二叉树由森林转换成二叉树的转换规则为:若 F = ,则 B = ;否则, 由 ROOT( T1 ) 对应得到 Node(root); 由 (t11, t12, , t1m ) 对应得到 LBT; 由 (T2, T3, Tn ) 对应得到 RBT。105由二叉树转换为森林由二叉树转换为森林的转换规则为:若 B = , 则 F = ;否则,由 Node(root) 对应得到 ROOT( T1 );由LBT 对应得到 ( t11, t12, ,t1m);由RBT 对应得到 (T2, T3, , Tn)。106BCDEFGHIJKLBCDEFKLGHIJ107 由此,树的各种操作均可对应二叉树
42、的操作来完成。 应当注意的是,应当注意的是,和树对应的二叉树,其左、右子树的概念已改变为: 左是孩子,右是兄弟。左是孩子,右是兄弟。1086.7树和森林的遍历树和森林的遍历109一、树的遍历一、树的遍历二、森林的遍历二、森林的遍历110树的遍历可有三条搜索路径树的遍历可有三条搜索路径:按层次遍历按层次遍历:先根先根(次序次序)遍历遍历:后根后根(次序次序)遍历遍历: 若树不空,则先访问根结点,然后若树不空,则先访问根结点,然后依次先根遍历各棵子树。依次先根遍历各棵子树。 若树不空,则先依次后根遍历各棵若树不空,则先依次后根遍历各棵子树,然后访问根结点。子树,然后访问根结点。 若树不空,则自上而
43、下自左至右若树不空,则自上而下自左至右访问树中每个结点。访问树中每个结点。111 A B C DE F G H I J K 先根遍历时顶点先根遍历时顶点的访问次序:的访问次序:A B E F C D G H I J K 后根遍历时顶点后根遍历时顶点的访问次序:的访问次序:E F B C I J K H G D A 层次遍历时顶点层次遍历时顶点的访问次序:的访问次序:A B C D E F G H I J K112 B C DE F G H I J K1森林中第一棵树的根结点;2森林中第一棵树的子树森林;3森林中其它树构成的森林。森林由三部分构成:1131. 先序遍历先序遍历森林的遍历森林的遍历
44、 若森林不空,则访问访问森林中第一棵树的根结点;先序遍历先序遍历森林中第一棵树的子树森林;先序遍历先序遍历森林中(除第一棵树之外)其 余树构成的森林。即:依次从左至右依次从左至右对森林中的每一棵树树进行先根遍历先根遍历。114中序遍历中序遍历 若森林不空,则中序遍历中序遍历森林中第一棵树的子树森林;访问访问森林中第一棵树的根结点;中序遍历中序遍历森林中(除第一棵树之外)其 余树构成的森林。即:依次从左至右依次从左至右对森林中的每一棵树树进行后根遍历后根遍历。115 树的遍历和二叉树遍历树的遍历和二叉树遍历的对应关系的对应关系 ?先根遍历先根遍历后根遍历后根遍历树树二叉树二叉树森林森林先序遍历先
45、序遍历先序遍历先序遍历中序遍历中序遍历中序遍历中序遍历116 最优树的定义 如何构造最优树 哈夫曼编码 117 一、最优树的定义一、最优树的定义树的路径长度树的路径长度定义为: 根结点到每个结点的路径长度之和。 结点的路径长度结点的路径长度定义为: 从树中一结点到另一结点的路径上分支的数目。118 树的带权路径长度树的带权路径长度定义为: 树中所有叶子结点的带权路径长度结点的带权路径长度之和 WPL(T) = wklk (对所有叶子结点)。 在所有含 n 个叶子结点、并带相同权值的 m 叉树中,必存在一棵其带权路径带权路径长度取最小值长度取最小值的树,称为“最优树最优树”。例如:例如:1192
46、2 4 75499WPL(T)= 72+52+23+43+92 =60WPL(T)= 72+91+53+24+44 =625712024579WPL(T)=9 2+7 2+5 2+2 3+4 3=60121 根据给定的 n 个权值 w1, w2, , wn, 构造 n 棵二叉树的集合 F = T1, T2, , Tn, 其中每棵二叉树中均只含一个带权值 为 wi 的根结点,其左、右子树为空树;二、如何构造最优树二、如何构造最优树(1)(哈夫曼算法) 以二叉树为例:122 在 F 中选取其根结点的权值为最 小的两棵二叉树,分别作为左、 右子树构造一棵新的二叉树,并 置这棵新的二叉树根结点的权值
47、为其左、右子树根结点的权值之 和;(2)123 从F中删去这两棵树,同时加入 刚生成的新树; 重复 (2) 和 (3) 两步,直至 F 中只 含一棵树为止。(3)(4)约定:为了保证得到的哈夫曼树结构尽量唯一,约定每个结点的左子树根结点权值小于等于右子树根结点的权值。1249例如: 已知权值 W= 5, 6, 2, 9, 7 5627527697671395271256713952795271667132900001111000111100101126三三哈夫曼编码哈夫曼编码 假设我们发送的电文为“ABACCD”,它只有四个字符,只需要2位二进制编码 A - 00 B - 01 C - 10
48、D - 11发送电文的序列为 000100101011 在传送电文时,要求总长度尽量短,因此出现次数多的字符适用短的编码。 A - 0 B - 00 C - 1 D - 11发送电文的序列为 00001111 (可以解释为AAAACCCC,AABDD,BBCCCC.)我们必须使用前缀编码前缀编码127前缀编码:任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀。如:A B C D 四个字符的使用率由高到低,编码为A - 0 B - 10 C - 110 D - 111做法:以字符概率作为叶子结点,构造二叉树,左分支标0;右分支标1;构成编码一定是前缀编码。 利用哈夫曼树可以构造一种不等
49、长的二进制编码,利用哈夫曼树可以构造一种不等长的二进制编码,并且构造所得的并且构造所得的哈夫曼编码哈夫曼编码是一种是一种最优前缀编码最优前缀编码,即,即使所传使所传电文的总长度最短电文的总长度最短。128例例. 假设字符假设字符A,B,C,D,E的出现次数为的出现次数为42,28,37,10,64 求求使所传使所传电文的总长度最短的一种编码?电文的总长度最短的一种编码?首先构建首先构建哈夫曼树(根据概率)哈夫曼树(根据概率)1028383775426410618111110000A - 10B - 011C - 00D - 010E - 11哈夫曼树及编码实现哈夫曼树及编码实现typedef
50、struct unsigned int weight; unsigned int parent,lchild,rchild; HTNode,*HuffmanTree; typedef char *HuffmanCode; / 动态分配数组存储赫夫曼编码表动态分配数组存储赫夫曼编码表129void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n) / w存放存放n个字符的权值个字符的权值(均均0),构造赫夫曼构造赫夫曼树树HT,并求出并求出n个字符的赫夫曼编码个字符的赫夫曼编码HC int m,i,s1,s2,start;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年马鞍山市公安局招聘警务辅助人员45人模拟试卷及参考答案详解
- 2025广东惠州市博罗县罗浮山文化旅游投资集团有限公司所属企业管理岗位遴选拟聘用考前自测高频考点模拟试题及答案详解(考点梳理)
- 2025湖北荆州市石首市面向城市社区党组织书记专项招聘事业岗位人员5人模拟试卷及一套答案详解
- 2025年乐山高新区管委会直属事业单位公开考核招聘工作人员的模拟试卷及一套完整答案详解
- 2025福建福州市招聘培训顾问1人考前自测高频考点模拟试题及答案详解(易错题)
- 2025江苏苏州卫生职业技术学院招聘35人考前自测高频考点模拟试题完整答案详解
- 2025江苏泰州机电高等职业技术学校招聘兼职车工实习教师2人模拟试卷及一套完整答案详解
- 2025贵州银行纪检人员招聘11人考前自测高频考点模拟试题及1套参考答案详解
- 2025广西玉林市福绵区石和镇人民政府招聘代理服务记账中心编外人员2人模拟试卷带答案详解
- 2025年宁波市北仑区大榭街道社区卫生服务中心招聘编外工作人员3人考前自测高频考点模拟试题及答案详解(历年真题)
- 2025年电力系统工程师高级专业试题及答案
- 2025年电商平台新业态发展趋势与运营策略研究报告
- 2025中粮集团社会招聘7人笔试历年参考题库附带答案详解
- 海南自贸港考试题及答案
- 2025年初级药师资格考试试题(附答案)
- 2025广东云浮市检察机关招聘劳动合同制司法辅助人员17人备考考试题库附答案解析
- 人工智能与建筑产业体系智能化升级研究报告
- 工装夹具设计培训课件
- 包覆拉拔法制备铜包铝、铜包钢双金属导线的多维度探究与展望
- 大气的受热过程教学课件
- 茶叶农药知识培训课件
评论
0/150
提交评论