收藏 分享(赏)

数据结构第六章树和二叉树.ppt

上传人:dzzj200808 文档编号:5750068 上传时间:2019-03-15 格式:PPT 页数:67 大小:2.25MB
下载 相关 举报
数据结构第六章树和二叉树.ppt_第1页
第1页 / 共67页
数据结构第六章树和二叉树.ppt_第2页
第2页 / 共67页
数据结构第六章树和二叉树.ppt_第3页
第3页 / 共67页
数据结构第六章树和二叉树.ppt_第4页
第4页 / 共67页
数据结构第六章树和二叉树.ppt_第5页
第5页 / 共67页
点击查看更多>>
资源描述

1、第六章 树和二叉树,第六章 树和二叉树,第六章 树和二叉树6.1 树的有关概念 6.2 二叉树 6.3 二叉树的遍历 6.4 遍历的应用 6.7 哈夫曼树及应用,第六章 树和二叉树,树形结构是一种重要的非线性结构,讨论的是层次和分支关系。 (1) 树的定义 树是n(n0)个结点的有限集,在任意一棵非空树中满足下面两个条件: 有且仅有一个特定的称为根的结点;,6.1 树的有关概念,1树的概念, 当n1时,其余结点可分为m(m0)个互不相交的有限集T1,T2, ,Tm,其中每个集合本身又是一棵树,并且称为根的子树。,(2) 图示,T=A, B, C, D, E, F, G, H, I, J,K,L

2、,M A是根,其余结点可以划分为3个互不相交的集合: T1=B, E, F,K,L, T2=C, G, T3=D, H, I, J,M 这些集合中的每一集合都本身又是一棵树,它们是A的子树。 例如,对于 T1,B是根,其余结点可以划分为2个互不相交的集合:T11=E,K,L,T12=F,T11,T12 是B的子树。,从逻辑结构看: 1)树中只有根结点没有前趋; 2)除根外,其余结点都有且仅一个前趋; 3)树的结点,可以有零个或多个后继; 4)除根外的其他结点,都存在唯一条从根到该结点的路径; 5)树是一种分枝结构 (除了一个称为根的结点外)每个元素都有且仅有一个直接前趋,有且仅有零个或多个直接

3、后继。, 树可表示具有分枝结构关系的对象,局,例1 家族族谱 设某家庭有13个成员A、B、C、D、E、F、G、H、I、J,K,L,M,他们之间的关系可用右图所示的树表示:,科1,科2,科3,室2,室2,室2,人,室1,室3,室1,室3,室1,室3,人,人,人,人,人,人,人,人,例2 单位行政机构的组织关系,2树的应用,例3 计算机的文件系统 不论是DOS文件系统还是window文件系统,所有的文件是用树的形式来组织的。, 广义表 (A (B (E(K,L),F),C(G),D(H(M),I,J), 凹入表 (类似书的目录), 嵌套集合,3 树的其他表示形式,5 基本术语, 结点(node):

4、 数据元素+若干指向其子树的分枝; 结点的度(degree):结点拥有的子树(分支)数; 叶子(终端结点 leaf):度为0的结点;, 分枝结点(非终端结点、内部结点):度不为0的结点; 树的度:树中所有结点的度的最大值; 孩子(child):结点的子树的根称为该结点的孩子; 双亲(parent):B结点是A结点的孩子,则A结点是B 结点的双亲; 兄弟(sibling):同一双亲的孩子之间的称呼; 祖先:根结点到该结点所经分枝上的所有结点; 子孙:以某结点为根的子树中任一结点都称为该结点的子孙, 层次(level):从根结点开始定义.根为第一层,根的孩子为第二层,若某结点在第 L 层,则其子树

5、的根就示第 L+1 层;, 堂兄弟:同一层上结点; 树的深度(高度 depth):树中结点的最大层次; 有序树:各子树看成从左至右是有次序的(即不能互换); 如:家族树 无序树:各子树从左至右是无序的(即能互换) ; 森林(forest):m(m0)棵树互不相交的集合。森林和树之间的联系是:一棵树去掉根,其子树构成一个森林;一个森林增加一个根结点成为树。,第六章 树和二叉树,树是一种分枝结构的对象,在树的概念中,对每一个结点孩子的个数没有限制,因此树的形态多种多样,本章我们主要讨论一种最简单的树二叉树。,6.2 二 叉 树,1、二叉树,(1) 二叉树的定义 二叉树(Binary Tree)是个

6、有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树。,二叉树是有序的,即若将其左、右子树颠倒,就成为另一棵不同的二叉树。即使树中结点只有一棵子树,也要区分它是左子树还是右子树。,说明 1)二叉树中每个结点最多有两颗子树;二叉树每个结点度小于等于2; 2)左、右子树不能颠倒有序树; 3)二叉树是递归结构,在二叉树的定义中又用到了二叉树的概念;,(2) 二叉树的五种基本形态:,N,空树,只含根结点,N,N,N,右子树为空树,左子树为空树,左右子树均不为空树,(4) 二叉树应用举例例1,例1 可以

7、用二叉树表示表达式,a+b*(c-d)-e/f,例2 双人比赛的所有可能的结局(五局三胜制),开局连赢两局 或五局三胜,2 二叉树的性质,性质1 在二叉树的第i层上至多有 2i-1 个结点(i1)。 性质2 深度为 k 的二叉树至多有 2k-1 个结点。(k1),性质3 对任何一棵二叉树, 如果其终端结点个数为n0,度为2的结点数为n2,则有 n0n21, 两类特殊的二叉树 满二叉树 深度为 k 且含有 2k-1 个结点的二叉树。,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 完全二叉树,树中所含的 n 个结点和满二叉树中编号为 1 至 n 的结点一一对应。,完全二

8、叉树,不是完全二叉树,、(b)完全二叉树 (c) 不是完全二叉树,性质4 具有 n 个结点的完全二叉树的深度为 log2n+1 。,性质5 如果将一棵有n个结点的完全二叉树(其深度为log2n+1)自顶向下,同一层自左向右连续给结点编号1, 2, , n-1,n,然后按此结点编号将树中各结点顺序地存放于一个一维数组中, 并简称编号为i的结点为结点 i(1in)。则有以下关系:, 若i = 1, 则 i 是二叉树的根,无双亲; 若i 1, 则 i 的双亲为PARENT(i)=i/2。 若 2in 则结点 i 无左孩子(是叶子结点);否则 i 的左孩子 LCHILD(i)=2i。 若2i+1n 则

9、结点 i 无右孩子(是叶子结点);否则 i 的右孩子 RCHILD(i)=2i+1。,性质5:在完全二叉树中编号为i的结点 1)若有左孩子,则左孩编号为2i 2)若有右孩子,则右孩子结点编号为2i+1 3)若有双亲,则双亲结点编号为trunc(i/2),1,2,3,4,5,6,3 二叉树的存储结构,二叉树的顺序结构完全二叉树的顺序结构, 概念:用一组连续的内存单元,按编号顺序依次存储完全二叉树的元素。例如,用一维数组bt 存放一棵完全二叉树,将标号为 i 的结点的数据元素存放在分量 bti-1中。存储位置隐含了树中的关系,树中的关系是通过完全二叉树的性质实现的。例如,bt5(i=6)的双亲结点

10、标号是k=trunc(i/2)=3,双亲结点所对应的数组分量btk-1=bt2,非完全二叉树的顺序结构按完全二叉树的形式补齐二叉树所缺少的那些结点,对二叉树结点编号,将二叉树原有的结点按编号存储到内存单元“相应”的位置上。但这种方式对于畸形二叉树,浪费较大空间。, 结构定义,#define maxtreesize 100 type telemtype sqbitreemaxtreesize; sqbitree bt; 注意适用性。,单支树,(2)二叉树的链式存储结构 概念:二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示着元素的逻辑关系。通常有下面两种形式。 结点结构,(结点)结

11、构定义 typedef struct BiTNode TElemType data; struct BiTNode *lchild;/左孩子指针 struct BiTNode *rchild;/右孩子指针 BiTNode,*BiTree;,图示,1、遍历二叉树的方法(Traversing binary tree),(1) 遍历二叉树的概念 遍历二叉树是指按某种搜索路径访问二叉树的每个结点,而且每个结点访问且仅被访问一次。 访问的含义很广,可以是对结点的各种处理,如修改结点数据、输出结点数据。 遍历是各种数据结构最基本的操作,许多其他的操作可以在遍历基础上实现。,6.3 二叉树的遍历,(2) 二

12、叉树的遍历方法 二叉树的遍历的特殊性 “遍历”是任何类型均有的操作,对线性结构而言,只有一条搜索路径(因为每个结点均只有一个后继),故不需要另加讨论。而二叉树是非线性结构,每个结点有两个后继,则存在如何遍历即按什么样的搜索路径遍历的问题。,对“二叉树”而言,可以有三条搜索路径:,I 先上后下的按层次遍历; II 先左(子树)后右(子树)的遍历; III 先右(子树)后左(子树)的遍历。, 二叉树的遍历方法 二叉树由根、左子树、右子树三部分组成;,二叉树的遍历可以分解为:访问根,遍历左子树和遍历右子树;,令:L:遍历左子树 T:访问根结点 R:遍历右子树 有六种遍历方法:T L R,L T R,

13、L R T,T R L,R T L,R L T 约定先左后右,有三种遍历方法:T L R、L T R、L R T,分别称为:先序遍历、中序遍历、后序遍历。, 三种遍历二叉树的(递归)操作定义,I 先序遍历二叉树的操作定义(T L R) 若二叉树为空,则为空操作;否则 a、访问根结点 b、先序遍历左子树, 即按T L R的顺序遍历左子树 c、先序遍历右子树, 即按T L R的顺序遍历右子树,先序遍历序列:A,B,D,E,G,C,F,II 中序遍历二叉树的操作定义(L T R)若二叉树为空,则为空操作;否则 a、中序遍历左子树,即按 L T R 的顺序遍历左子树 b、访问根结点 c、中序遍历右子树

14、,即按 L T R 的顺序遍历右子树,中序遍历序列: D,B,G,E,A,C,F,III 后序遍历二叉树的操作定义(L R T),若二叉树为空,则空操作,否则 a、后序遍历左子树, 即按L R T的顺序遍历左子树 b、后序遍历右子树, 即按L R T的顺序遍历右子树 c、访问根结点,后序遍历序列:D,G,E,B,F,C,A,例:先序、中序、后序遍历右图所示的二叉树,先序序列:+,*,a,-,b,c,/,d,e -表达式的前缀表示(波兰式)中序序列:a,*,b,-,c,+,d,/,e -表达式的中缀表示 后序序列:a,b,c,-,*,d,e,/,+ -表达式的后缀表示(逆波兰式),二. 三种遍历

15、二叉树的递归算法,上面先序遍历的定义等价于: 若二叉树为空,结束 基本项(也叫终止项) 若二叉树非空 递归项(1)访问根结点;(2)先序遍历左子树(3)先序遍历右子树;, 前序 int preordertraverse(BiTree t,int (*visit)(telemtype) if(t) visit(tdata); preordertraverse(tlchild,visit(telemtype); preordertraverse(trchild,visit(telemtype); ,a*(b-c)+d/e, 中序 int inordertraverse(BiTree t,int (

16、*visit)(telemtype) if(t) inordertraverse(tlchild,visit(telemtype); visit(tdata); inordertraverse(trchild,visit(telemtype); , 后序 int postordertraverse(BiTree t,int (*visit)(telemtype) if(t) postordertraverse(tlchild,visit(telemtype); postordertraverse(trchild,visit(telemtype); visit(tdata); ,+, 三种遍历过

17、程示意图,a*(b-c)+d/e,*,a,-,b,c,/,d,e,+,*,a,b,-,c,d,/,e,+,/,e,d,*,-,+,b,e,先序,中序,后序,三. 三种遍历二叉树的非递归算法, 前序 分析:对每个结点,在访问完后,沿其左链一直访问下来,直到左链为空,这时,所有已被访问过的结点进栈。然后结点出栈,对于每个出栈结点,即表示该结点和其左子树已被访问结束,应该访问该结点的右子树。 I 当前指针指向根结点; II 输出当前结点,当前结点指针进栈,然后指向其左孩子,重复 II,直到左孩子为NULL; III 依次退栈,将当前指针指向右孩子; IV 若栈非空或当前指针非NULL,执行 II;否

18、则结束。,递归算法逻辑清晰、易懂,但在实现时,由于函数调用栈层层叠加, 效率不高,故有时考虑非递归算法。,int preorder(BiTree t) BiTree stack50; int top; top=-1; dowhile(t!=NULL) cprintf(“%c“,t-data); top+; stacktop=t; t=t-lchild; if(top=0) t=stacktop; top-; t=t-rchild; while(top=0|t!=NULL); ,前序遍历二叉树的非递归算法描述,cprintf(“%c“,t-data);,top+;,+,stacktop=t;,t

19、=t-lchild;,cprintf(“%c“,t-data);,*,top+;,stacktop=t;,t=t-lchild;,cprintf(“%c“,t-data);,a,top+;,stacktop=t;,t=t-lchild;,t=stacktop;,top-;,t=t-rchild;,t=stacktop;,top-;,t=t-rchild;,cprintf(“%c“,t-data);,-,top+;,stacktop=t;,t=t-lchild;,cprintf(“%c“,t-data);,b,top+;,stacktop=t;,t=t-lchild;,t=stacktop;,t

20、op-;,t=t-rchild;,t=stacktop;,top-;,t=t-rchild;,cprintf(“%c“,t-data);,c,top+;,stacktop=t;,t=t-lchild;,t=stacktop;,top-;,t=t-rchild;,t=stacktop;,top-;,t=t-rchild;,cprintf(“%c“,t-data);,/,top+;,stacktop=t;,t=t-lchild;,cprintf(“%c“,t-data);,d,top+;,stacktop=t;,t=t-lchild;,t=stacktop;,top-;,t=t-rchild;,t

21、=stacktop;,top-;,t=t-rchild;,cprintf(“%c“,t-data);,e,top+;,stacktop=t;,t=t-lchild;,t=stacktop;,top-;,t=t-rchild;,while(top=0|t!=NULL);,node ,printf(“%c,”, root-data);,+,nodetop=p;,top+;,p=p-lch;,printf(“%c,”, root-data);,*,nodetop=p;,top+;,p=p-lch;,printf(“%c,”, root-data) ;,a,nodetop=p;,top+;,p=p-l

22、ch;,if (top0),top - -;,p=nodetop;,p=p-rch;,printf(“%c,”, root-data) ;,-,nodetop=p;,top+;,p=p-lch;,b,top - -; p=nodetop; p=p-rch;,c,printf(“%c,”, root-data),nodetop=p;,top+;,p=p-lch;,top - -;,p=nodetop;,p=p-rch,printf(“%d,”, root-data) ;,/,nodetop= p;,top+;,p = p - lchild;,d,6.4 遍历的应用,遍历是二叉树的基本操作:二叉树

23、许多操作可在遍历过程中完成,本节再举几个二叉树遍历应用实例。,(1) 求二叉树各结点的层数 int levelnum(bitree t,int num) if(t=NULL) return(0); else num+; cprintf(“%c-%d “,t-data,num); levelnum(t-lchild,num)+levelnum(t-rchild,num); , 求二叉树的深度,int depth(BiTree t) int dep1=0, dep2=0; if(t=NULL) return(0); else dep1=depth(t-lchild); dep2=depth(t-r

24、child); if(dep1dep2) return(dep1+1); else return(dep2+1); ,例 编写 求二叉树的叶子结点个数的算法 输入:二叉树的二叉链表 结果:二叉树的叶子结点个数,root,void leaf(BiTree *root) /采用二叉链表存贮二叉树,n为全局变量,用于累加二叉树的叶子结点 /的个数。本算法在先序遍历二叉树的过程中,统计叶子结点的个数 /第一 次被调用时,n=0if(root!=NULL) if(root- lchild = =NULL ,与先序遍历算法比较一下!,求二叉树叶子数,int leafnum(bitree t) if(t=N

25、ULL) return(0); else if(t-lchild=NULL ,比较先序遍历算法和计算叶子结点算法,有什么相同和不同?,结构类似,函数名不同,访问结点时 调用printf( ),访问结点时 统计叶子结点的个数,void prev (BiTree *root) if (root!=NULL) printf(“%d,”, root-data); prev(root-lchild); prev(root-rchild); ,void leaf(BiTree *root) if(root!=NULL) if(root-lchild= =NULL ,例 建立二叉链表输入:二叉树的先序序列结

26、果:二叉树的二叉链表,遍历操作访问二叉树的每个结点,而且每个结点仅被访问一次。是否可在利用遍历,建立二叉链表的所有结点并完成相应结点的链接?,基本思想:输入(在空子树处添加字符*的二叉树的)先序序列(设每个元素是一个字符)按先序遍历的顺序,建立二叉链表的所有结点并完成相应结点的链接,A B D * F * * * C E * * *,输入(在空子树处添加空格字符的二叉树的)先序序列(设每个元素是 一个字 符)按先序遍历的顺序,建立二叉链表,并将该二叉链表根结 点指针赋给rootBiTree *create_tree(BiTree *root) char ch;scanf ( /结点指针赋给(根

27、)结点 的右孩子域 ,T,先序序列:A B D F C E,(在空子树处添加*的二叉树的)先序序列:A B D F C E,6.7 哈夫曼树及应用,1、最优二叉树(赫夫曼(Huffman)树),(1) 路径及路径长度,n个结点的二叉树的路径长度不小于下述数列前n项的和,即, 路径:从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。 路径长度:路径上的分支数目。 树的路径长度:从树根到每一结点的路径长度之和。,在结点数相同的条件下,完全二叉树是路径最短的二叉树。,其路径长度最小者为,(2) 树的带权路径长度, 带权结点:含权值的结点。根据需要可以给树的结点赋权值。 结点的带权路径长度

28、:从该结点到树根之间路径长度与结点上权的乘积。 树的带权路径长度:树中所有叶子结点的带权路径长度之和。记为,(3) 最优二叉树(赫夫曼树) 概念:设有n个权值量W1, W2, Wn,构造一棵有n个叶子结点的二叉树,每个叶子的结点带权为Wi,则其中WPL最小的二叉树称做最优二叉树(赫夫曼树)。 相同结点及权值构造不同的二叉树得到不同WPL的示例,一个软件小组四个人,由于业务和工作关系,找组长A频率是8,找副组长B的频率是5,找负责数据库程序员C的频率是3,找负责网络程序员D的频率是2,以这些频率为权的带权叶子结点所构成的三棵二叉树如下:,其带权路径长度分别为: (a) WPL=82+52+32+

29、22=36 (b) WPL=83+53+32+21=47 (c) WPL=81+52+33+23=33 可以验证(c)即为赫夫曼树。,若用线性表来组织查找的话,其最小值为35,体现了用构造赫夫曼树来解决这类问题的优越性。, 判定问题,设有10000个百分制分数要转换,设学生成绩在5个等级以上的分布如下:,例如下面的程序: if(a60) p=“bad”; else if(a70) p=“pass”; else if(a80) p=“general”; else if(a90) p=“good”; else p=“excellent”;,按图的判定过程: 转换一个分数所需的比较次数=从根到对应结

30、点的路径长度 转换10000个分数所需的总比较次数= 10000 (0.051+0.152+0.43+0.34+0.1 4)=31500,可有不同的判定过程,最佳判定过程为:,总共仅需进行 10000 (0.053+0.153+0.42+0.32+0.12)=22000 次比较 此二叉树可以认为是满足一定条件的赫夫曼树。是为了减少比较而使得权值相对较小的结点不在相对层次较低的位置上。 (4) 赫夫曼树的构造 构造思想,把所要构造的带权结点都构造在赫夫曼树的叶子位子,权值较大的结点构造在离根结点较近的叶子位子,权值较小的结点构造在离根结点较远的叶子位子,以使得带权路径的长度之和最小。, 构造方法

31、 I 根据给定的n个权值W1, W2,Wn构成n棵二叉树的集合F=T1, T2,Tn,其中每棵二叉树Ti中只有一个带权的Wi的根结点,其左右子树均空。 II 在F中选取两棵根结点的权值最小的树作为左、右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。 III 在F中删除这两棵树,同时将新得到的二叉树加入F中。 IV 重复 II 和 III,直到F只含一棵树为止,这棵树便是赫夫曼树。 构造过程,构造以W=(5,15,40,30,10)为权的哈夫曼树。,哈夫曼树中 权值小的结点离根远 权值大的结点离根近,2、赫夫曼编码,(1) 引入 在进行数据通讯时,涉及数据

32、编码问题。所谓数据编码就是数据与二进制字符串的转换。例如:邮局发电报:,例 要传输的原文为ABACCDA 等长编码 A:00 B:01 C:10 D:11 发送方: 将ABACCDA 转换成 00010010101100 接收方: 将 00010010101100 还原为 ABACCDA,不等长编码 A:0 B:00 C:1 D:01 发送方: 将ABACCDA 转换成 000011010,AAAACCDA,A的编码是B的前缀,接收方: 000011010 转换成,BBCCDA,(2) 前缀编码,所以,构造的编码不应是其它编码的前缀,即任一字符的编码都不是另一字符的编码的前缀,这种编码称做前缀编码。,若约定左分支表示字符“0”,右分支表示字符“1”,则上例中由赫夫曼树所得到的A,B,C,D,E的编码:1110,110,1,10,1111就是前缀编码,即赫夫曼编码。所得的译码是唯一的。,为使编码的总长度尽可能的短,若只考虑每个编码尽可能的短,很有可能使一个编码是另一个编码的前缀,从而无法译码。,(3) 赫夫曼树问题 如何得到编码总长最短的二进制前缀编码呢? 设文中字符出现的次数为Wi,其编码长度为Li,文中有n种字符,则文总长为 wili,即为以n个字符出现的频率为权,二叉树上带权路径的长度最小,既是设计一棵赫夫曼树的问题。,小 结,

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

当前位置:首页 > 中等教育 > 职业教育

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


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

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

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