收藏 分享(赏)

第06章 树和二叉树.ppt

上传人:HR专家 文档编号:11821278 上传时间:2021-01-31 格式:PPT 页数:70 大小:449.50KB
下载 相关 举报
第06章 树和二叉树.ppt_第1页
第1页 / 共70页
第06章 树和二叉树.ppt_第2页
第2页 / 共70页
第06章 树和二叉树.ppt_第3页
第3页 / 共70页
第06章 树和二叉树.ppt_第4页
第4页 / 共70页
第06章 树和二叉树.ppt_第5页
第5页 / 共70页
点击查看更多>>
资源描述

1、第六章 树和二叉树,树的概念和基本术语 二叉树 二叉树遍历 树与森林,本章主要内容:,一、树的概念和基本术语,1、树的定义 树是由 n (n 0) 个结点的有限集合。如果 n = 0,称为空树;如果 n 0,则 有且仅有一个特定的称之为根(Root)的结点,它只有直接后继,但没有直接前驱; 当n 1,除根以外的其它结点划分为 m (m 0) 个互不相交的有限集 T1, T2 , Tm,其中每个集合本身又是一棵树,并且称为根的子树(SubTree)。,例如,A,只有根结点的树,有13个结点的树,其中:A是根;其余结点分成三个互不相交的子集, T1=B,E,F,K,L; T2=C,G; T3=D,

2、H,I,J,M, T1,T2,T3都是根A的子树,且本身也是一棵树,2、树的基本术语,1层,2层,4层,3层,height = 4,A,C,G,B,D,E,F,K,L,H,M,I,J,结点 结点的度 分支结点 叶结点,子女 双亲 兄弟,祖先 子孙 结点层次,树的度 树的深度 森林,二、二叉树,定义,五种形态,:二叉树是一种特殊类型的树,它是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成。,特点:,每个结点至多只有两棵子树(二叉树中 不存在度大于2的结点),1、二叉树的概念与性质,性质1:在二叉树的第 i 层上至多有 2i 1个结点。(i 1) 证明用归纳法 证明:当i=1时

3、,只有根结点,2 i-1=2 0=1。 假设对所有j,ij1,命题成立,即第j层上至多有2 j-1 个结点。 由归纳假设第i-1 层上至多有 2i 2个结点。 由于二叉树的每个结点的度至多为2,故在第i层上的最大结点数为第i-1层上的最大结点数的2倍,即2* 2i 2= 2 i-1。,性质,性质2 :深度为 k 的二叉树至多有 2 k-1个结点(k 1)。 证明:由性质1可见,深度为k的二叉树的最大结点数为,性质3:对任何一棵二叉树T, 如果其叶结点数为 n0, 度为2的结点数为 n2,则n0n21. 证明:若度为1的结点有 n1 个,总结点个数为 n,总边数为 e,则根据二叉树的定义, n

4、= n0 + n1 + n2 e = 2n2 + n1 = n - 1 因此,有 2n2 + n1 = n0 + n1 + n2 - 1 n2 = n0 - 1 n0 = n2 + 1,定义1 满二叉树 (Full Binary Tree) 一棵深度为k且有2 k-1个结点的二叉树称为满二叉树。,两种特殊形态的二叉树,满二叉树,非完全二叉树,定义2 完全二叉树 (Complete Binary Tree) 若设二叉树的高度为h,则共有h层。除第 h 层外,其它各层 (0 h-1) 的结点数都达到最大个数,第 h 层从右向左连续缺若干结点,这就是完全二叉树。,完全二叉树,性质4 具有 n (n

5、0) 个结点的完全二叉树的深度为log2(n) 1 证明: 设完全二叉树的深度为 h,则根据性质2和完全二叉树的定义有 2h1 - 1 n 2h- 1或 2h1 n 2h 取对数 h1 log2n h,又h是整数, 因此有 h = log2(n) 1,性质5 如将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号0, 1, 2, , n-1,则有以下关系: 若i = 0, 则 i 无双亲 若i 0, 则 i 的双亲为(i -1)/2 若2*i+1 n, 则 i 的左子女为 2*i+1,若2*i+2 n, 则 i 的右子女为2*i+2,0,7,1,2,3,4,5,6,8,9,完全二

6、叉树 一般二叉树 的顺序表示 的顺序表示,2、二叉树的存储结构,1,1 2 3 4 5 6 7 8 910,9,1 2 3 4 0 5 6 7 8 0 0 910,2,4,8,9,10,5,6,7,3,1,2,3,6,5,4,7,8,顺序表示,9,10,链表表示,二叉链表,含两个指针域的结点结构,lChild data parent rChild,含三个指针域的结点结构,三叉链表,二叉树链表表示的示例,A,A,A,B,B,B,C,C,C,D,D,D,F,F,F,E,E,E,root,root,root,二叉树 二叉链表 三叉链表,三叉链表的静态结构,typedef char ElemType;

7、/结点数据类型 typedef struct BiTNode /结点定义 ElemType data; struct BiTNode * lchild, * rchild; BiTNode,*BiTree;,二叉链表的定义,3、二叉树遍历,树的遍历就是按某种次序访问树中的结点,要求每个结点访问一次且仅访问一次。 设访问根结点记作 V 遍历根的左子树记作 L 遍历根的右子树记作 R 则可能的遍历次序有 先序 VLR 中序 LVR 后序 LRV,中序遍历二叉树算法的定义: 若二叉树为空,则空操作; 否则 中序遍历左子树 (L); 访问根结点 (V); 中序遍历右子树 (R)。 遍历结果 a + b

8、 * c - d - e / f,中序遍历,void InOrderTraverse ( BiTree T, int (*visit(ElemType data ) if (T) InOrderTraverse ( T-lchild ); visit(T-data); InOrderTraverse ( T-rchild ); ,中序遍历二叉树的递归算法演示,前序遍历二叉树算法的定义: 若二叉树为空,则空操作; 否则 访问根结点 (V); 前序遍历左子树 (L); 前序遍历右子树 (R)。 遍历结果 - + a * b - c d / e f,先序遍历 (Preorder Traversal)

9、,前序遍历二叉树的递归算法演示 void PreOrderTraverss ( BiTree T, int(*visit )(ElemType data) if ( T ) visit( T-data); PreOrderTraverss ( T-lchild ); PreOrderTraverss ( T-rchild ); ,后序遍历二叉树算法的定义: 若二叉树为空,则空操作; 否则 后序遍历左子树 (L); 后序遍历右子树 (R); 访问根结点 (V)。 遍历结果 a b c d - * + e f / -,后序遍历 (Postorder Traversal),后序遍历二叉树的递归算法

10、演示 void PostOrderTraverss ( BiTree T, int (*visit)(ElemType data) ) if ( T ) PostOrderTraverss ( T-lchild ); PostOrderTraverss ( T-rchild ); visit( T-data); ,4、二叉树主要操作,void CreateBiTree(BiTRee ,按前序建立二叉树演示,int CountBiTNods ( BinTreeNode *T ) if ( !T ) return 0; else return 1 + CountBiTNods ( T-lchild

11、 ) + CountBiTNods ( T-rchild ); ,计算二叉树结点个数(递归算法),int CountLeafs (Bitree T) /求二叉树中叶子结点的数目 if(!T) return 0; /空树没有叶子 else if(!T-lchild /左子树的叶子数加上右子树的叶子数/Leaf_Count,求二叉树中叶子结点的个数,int CountHeight ( BiTree T ) if ( !T) return 0; else int m =CountHeight ( T-lchild ); int n =CountHeight ( T-rchild ) ); retur

12、n (m n) ? m+1 : n+1; ,求二叉树高度(递归算法),中序遍历二叉树(非递归算法)用栈实现,b a,a b入栈,b退栈 访问,d入栈,d退栈 访问,e 退栈 访问,e c,栈空,a退栈 访问,c e 入栈,c 退栈 访问,void InOrderTraverss ( BiTree T ) stack S; InitStack( 演示,前序遍历二叉树(非递归算法)用栈实现,a,c,a,b,c,d,e,d c,c,访问 a 进栈 c 左进 b,访问 b 进栈 d 左进 空,退栈 d 访问 d 左进 空,退栈 c 访问 c 左进 e,访问 e 左进 空 退栈 ,结束,void Pre

13、OrderTraverss( BiTree T ) stack S; InitStack(S); /递归工作栈 BiTree p = T; Push (S, NULL); while ( p ) visit( p-data); if ( p-rchild ) Push ( S, p-rchild ); if ( p-lchild ) p = p-lchild;/进左子树 else Pop( S, p ); ,a,b,c,d,e,LTag=0, Lchild为左孩子 LTag=1, Lchild为前驱线索 RTag=0, Rchild为右孩子 RTag=1, Rchild为后继指针,Lchild

14、,Rchild,data,LTag,RTag,5、线索二叉树 (Threaded Binary Tree),结点结构,typedef enum PointerTagLink=0,Thread=1 /Link=0:指针,Thread=1:线索; typedef struct BiThrNode ElemType data; struct BithrNode *lchild,*rchild; PointerTag LTag,RTag; /左右标志 BiThrNode,*BiThrTree;,线索二叉树存储结构,中序遍历二叉线索树 void InOrderTraverss_Thr(BiThrTree

15、 T, int(*visit)(ElemType data) BiThrTree p=T-child; /P指向根结点 whild(p!=T) /空树或遍历结束时,p=T while(p-LTag=Link)p=p-child; visit(p-data); while(p-RTag=Thread 演示,线索二叉树的部分操作,中序遍历二叉树,并将其线索化 演示,void InOrderThreading(BiThrTree ,void InThreading(BiThrTree p) if(p) InThreading(p-lchild); /左子树线索化 if(!p-lchild) /前驱线

16、索 p-LTag=Thread; p-lchild=pre; if(!pre-rchild) /后继线索 pre-RTag=Thread; pre-rchild=p; pre=p; /保持pre 指向p的前驱 InThreading(p-rchild); /右子树线索化 return; ,1、树的存储结构 双亲表示:以一组连续空间存储树的结点,同时在结点中附设一个指针,存放双亲结点在链表中的位置。,三、树和森林,用双亲表示实现的树定义,#define MaxSize /最大结点个数 typedef struct /树结点定义 ElemType data; int parent; PTNode;

17、 typedef struct PTNode nodesMaxSize; /树 int r,n; PTree;,孩子链表表示法,第一种解决方案 等长的链域,data,child1,child2,childd1,变长的链域,data,child1,child2,childd2,空链域n(k-1)+1,第二种解决方案,CTNode,CTBox,CTree,孩子链表表示法存储结构,typedef struct CTNode int child; struct CTNode *next; *ChildPtr; typedef struct char data; ChildPtr firstchild;

18、 CTBox; typedef struct CTBox nodesMAX_TREE_SIZE; int r,n; CTree;,结点结构,空链域n+1个,树的孩子-兄弟表示(二叉链表表示),typedef char ElemType; typedef struct ElemType data; struct node *firstChild, *nextSibling; CSNode,*CSTree;,用左子女-右兄弟表示实现的树定义,T1 T2 T3,T1 T2 T3,A,B,C,E,D,H,I,K,J,F,G,3 棵树的森林,各棵树的二叉树表示,森林的二叉树表示,2、森林与二叉树的转换,

19、树的二叉树表示:,3、树的遍历,深度优先遍历 先序遍历 后序遍历,A,B,C,E,D,G,F,左孩子右兄弟,深度优先遍历,当树非空时 访问根结点 依次先根遍历根的各棵子树 树先根遍历 ABEFCDG 对应二叉树前序遍历 ABEFCDG 树的先根遍历结果与其对应二叉树 表示的前序遍历结果相同 树的先根遍历可以借助对应二叉树的前序遍历算法实现,A,B,C,E,D,G,F,树的先序遍历,树的后序遍历:,当树非空时 依次后根遍历根的各棵子树 访问根结点 树后根遍历 EFBCGDA 对应二叉树中序遍历 EFBCGDA 树的后根遍历结果与其对应二叉树 表示的中序遍历结果相同 树的后根遍历可以借助对应二叉树

20、的中序遍历算法实现,A,B,C,E,D,G,F,四、霍夫曼树 (Huffman Tree),路径长度 (Path Length) 从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。 树的外部路径长度是各叶结点(外结点)到根结点的路径长度之和 EPL。 树的内部路径长度是各非叶结点(内结点)到根结点的路径长度之和 IPL。 树的路径长度 PL = EPL + IPL,1、基本概念,1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,树的外部路径长度 EPL = 3*1+2*3 = 9,树的外部路径长度 EPL = 1*1+2*1+3*1+4*1 = 10,1,带权路径长度 (

21、Weighted Path Length, WPL) 树的的带权 路径长度是树的各叶结点所带的权值 wi 与该结点到根的路径长度 li 的乘积之和。,WPL = 2*2+ WPL = 2*1+ WPL = 7*1+ 4*2+5*2+ 4*2+5*3+ 5*2+2*3+ 7*2 = 36 7*3 = 46 4*3 = 35,带权路径 长度达到最小,2、霍夫曼树,带权路径长度达到最小的二叉树即为霍夫曼树。 在霍夫曼树中,权值大的结点离根最近。,(1) 由给定的 n 个权值 w0, w1, w2, , wn-1,构造具有 n 棵二叉树的集合 F = T0, T1, T2, , Tn-1 ,其中每棵二

22、叉树 Ti 只有一 个带权 wi 的根结点, 其左、右子树均为空。,3、如何构造霍夫曼树-霍夫曼算法,(2) 重复以下步骤, 直到 F 中仅剩下一棵树为止: 在 F 中选取两棵根结点的权值最小的二叉树, 做为左、右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。 在 F 中删去这两棵二叉树。 把新的二叉树加入 F。,F : 7 5 2 4,F : 7 5 6,F : 7 11,7,5,2,4,初始,合并2 4,F : 18,11,7,5,2,4,6,合并5 6,5,合并7 11,2,7,4,6,11,18,举例:霍夫曼树的构造过程,5,2,7,4,Weigh

23、t parent leftChild rightChild,7 -1 -1 -1 5 -1 -1 -1 2 -1 -1 -1 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1,0 1 2 3 4 5 6,上例存储结构,初 态,5,2,7,4,6,Weight parent leftChild rightChild,7 -1 -1 -1 5 -1 -1 -1 2 -1 -1 -1 4 -1 -1 -1 6 -1 -1 -1 -1 -1 -1 -1 -1 -1,0 1 2 3 4 5 6,p1,p2,4,4,2,3,i,过 程,5,2,7,4,6,11,Weight pa

24、rent leftChild rightChild,7 -1 -1 -1 5 -1 -1 -1 2 4 -1 -1 4 4 -1 -1 6 -1 2 3 11 -1 -1 -1 -1 -1 -1,0 1 2 3 4 5 6,p1,p2,5,5,1,4,i,5,2,7,4,6,11,Weight parent leftChild rightChild,7 -1 -1 -1 5 5 -1 -1 2 4 -1 -1 4 4 -1 -1 6 5 2 3 11 -1 1 4 18 -1 -1 -1,0 1 2 3 4 5 6,p1,p2,6,6,0,5,i,18,终 态,3、霍夫曼编码,主要用途是实现数

25、据压缩。,设给出一段报文: CAST CAST SAT AT A TASA 字符集合是 C, A, S, T ,各个字符出现的频度(次数)是 W 2, 7, 4, 5 。 若给每个字符以等长编码 A : 00 T : 10 C : 01 S : 11 则总编码长度为 ( 2+7+4+5 ) * 2 = 36.,若按各个字符出现的概率不同而给予不等长编码,可望减少总编码长度。 各字符出现概率为 2/18, 7/18, 4/18, 5/18 ,化整为 2, 7, 4, 5 。以它们为各叶结点上的权值, 建立霍夫曼树。左分支赋 0,右分支赋 1,得霍夫曼编码(变长编码)。,7,2,5,4,0,1,0

26、,0,1,1,A,C,T,S,A : 0 T : 10 C : 110 S : 111 它的总编码长度:7*1+5*2+( 2+4 )*3 = 35。比等长编码的情形要短。 总编码长度正好等于霍夫 曼树的带权路径长度WPL。 霍夫曼编码是一种前缀 编码,即任何一个字符的 编码都不是另一个字符的 编码的前缀。 解码时不会混淆。,霍夫曼编码树,解码方向,编码方向,const int n = 20;/叶结点数 const int m = 2*n -1;/结点数 typedef struct unsigned int weight; int parent, lchild, rchild; HTNode

27、; *HuffmanTree;/动态分配数组存储霍夫曼树 typedef char *HuffmanCode; /动态分配数组存储霍夫曼编码表,4、霍夫曼树和霍夫曼编码的存储表示,5、求霍夫曼编码的算法演示 void HuffmanCode ( HuffmanTree +i)/建霍夫曼树 /在HT1.i-1选择parent为0且weight最小的两个结点,其序号分别为s1和s2.,select(HT,i-1,s1,s2); HTs1.parent=i;HTs2.parent=i; HTi.lchild=s1;HTi.rchild=s2; HTi.weight=HTs1.weight+HTs2.

28、weight; /从叶子到根逆向求每个字符的霍夫曼编码 HC=(HuffmanCode)malloc(n+1)*sizeof(char*); /分配n个字符编码的头指针向量 cd=(char*)malloc(n*sizeof(char); /分配求编码的工作空间 cdn-1=0; /编码结束符 for(i=1;i+n;i+) start=n-1;,for(c=i;f=HTi.parent;f!=0;c=f,f=HTf.parent) /从叶子到根逆向求编码 if(HTf.lchild=c) cd-start=0; else cd-start=1; HTi=(char*)malloc(n-sta

29、rt)*sizeof(char) /为第i个字符编码分配空间 strcpy(HCi, ,6、霍夫曼树的应用-最佳判定树,考试成绩分布表,判定树,不及格,及格,中,良,优,60?,70?,80?,90?,0.10,0.15,0.25,0.35,0.15,WPL = 0.10*1+0.15*2+0.25*3+0.35*4+0.15*4 = 3.15,最佳判定树,不及格,及格,中,良,优,60?,70?,80?,90?,0.10,0.15,0.25,0.35,0.15,WPL = 0.10*3+0.15*3+0.25*2+0.35*2+0.15*2 = 0.3+0.45+0.5+0.7+0.3 = 2.25,

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

当前位置:首页 > 中等教育 > 小学课件

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


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

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

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