《2.5树与二叉树.doc》由会员分享,可在线阅读,更多相关《2.5树与二叉树.doc(14页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、2.5树与二叉树树型结构是一类很重要的非线性数据结构,在这类结构中,元素结点之间存在明显的分支和层次关系。2.5.1 树的定义及其存储结构1. 树的定义和术语树是由n个(n0)结点组成的有限集合T,其中有且仅有一个结点称为根结点(root),其余结点可以分为m(m0)个互不相交的有限集合T1,T2,Tm,其中每个集合Ti本身又是一棵树,称为根结点root的子树。当n=0时称为空树。这是一个递归的描述,即在买偶数树时又用到树本身这个术语。图2.33所示为一棵树,A为根结点,期于结点分为三个不相交的子集T1,T2,T3,它们均为根结点A下的三棵树,而这三棵树本身也是树。 用二元组关系来定义树为 T
2、ree=(T,R)数据结构树(Tree)由数据元素集合T及各种R组成,其中T 是具有相同类型的数据元素集合T =x1,x2,xn。若T为空集(T=),则R=,称为空树,否则R是T上某个二元关系H的集合,即R=H。H的描述如下:(1)在T中存在唯一的称为根的元素root,它在H关系下无前趋。(2)若T-root,则存在m个子集T1,T2,Tm(m0),对任意的jk(1j,km),有TjTk= ,则存在唯一的数据元素xiTi(1im),满足H。(3)对应于 T1,T2,Tm,H-,满足H1,H2,Hm(m0),对任意的jk(1j,km)有HjHk= ,Hj满足在Ti上的二元关系。因此(Ti,Hi)
3、也是一棵符合本定义的树,称为根root的子树。树结构中常用的术语有.结点(node):表示树中的元素。.结点的度(degree):结点拥有的子树数,如图2.33中结点A的度为3,C的度为1。一棵树中最大的结点度数为这棵数的度,图2.33中树的度为3。.叶子(leaf):度为零的结点,又称为端结点。.孩子(child):除根结点外,每个结点都是其前趋结点的孩子。.双亲(parents):对应上述孩子结点的上层结点称为这些结点的双亲。例如图2.33中,D是A的孩子,A是D,C,B的双亲。.兄弟(sibling):同一双亲的孩子。.结点的层次(level):从根结点开始算起,根为第一层,根的直接后继
4、结点为第二层,其余个层次依次类推。例如图2.33中共分为4层。.深度(depth):树中结点的最大层次数。图2.33中树的深度为4。.森林(forest):是m(m0)棵互不相交的树的集合。.有序树:树中结点在同层中按从左至右有序排列、不能互换的称为有序树,反之称为无序树。2. 树的存储结构仅讨论链式存储结构。异构型:节省存储空间,运算不便。同构型:运算方便,浪费空间。假设有一棵具有n个结点的k叉树,则有nk个指针域,其中有用的指针域为n-1个,因此空链域个数为nk-(n-1)=n(k-1)+1个。不同的k值进行比较: k越大,空链域比例越高,k=2时比例最低,因此着重讨论二叉树结构。2.5.
5、 2二叉树及其性质1. 二叉树定义及其存储结构二叉树是n(n0)个结点的有限集合,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成。通常用具有两个指针域的链表作为二叉树的存储结构,其中每个结点由数据域(data)、左指针域(L child)和右指针域(R child)组成,即L childdataR child二叉树的链表结构如图2.35(b)所示。2. 二叉树的基本性质(1) 二叉树的第I层上至多有2i-1(i1)个结点。1,21-12,22-1.20+21+22+23+2h-1 =1+20+21+22+23+2h-1-1=2h-1(2) 深度为h的二叉
6、树中至多含有2h-1个结点。 1,21-12,22-1(3) 在任意二叉树中,若有n0个叶子结点,n2个度为2 的结点,则必有:n0=n2+1。每增加一个度为2的结点,叶子结点就增加一个。3. 几种特殊形式的二叉树(1) 满二叉树:深度为h含有2h-1个结点的二叉树为满二叉树。图2.36所示为一棵深度为4的满二叉树。(2) 完全二叉树如果一棵n个结点的二叉树,按与满二叉树相同的编号方式对结点进行编号,若树中n个结点和满二叉树1n编号完全一致,则称该树 为完全二叉树,如图2.37(a)所示;而图2.37(b)就不是完全二叉树。(3) 平衡二叉树平衡二叉树或者是一棵空树,或者是具有下列性质的二叉树
7、:它的左子树和右子树都是平衡二叉树 ,且左子树和右子树的深度之差的绝对值不超过1。图2.38(a)为平衡二叉树,(b)为不平衡二叉树。4. 一般树转换为二叉树(1) 在兄弟结点之间加一连线;(2) 对每个结点,除了与它的第一个孩子保持联系外,去除与其它孩子的联系;(3) 以树根为轴心,将整棵树顺时针旋转45。2.5.3二叉树的遍历遍历是指遵循某条搜索路线,依次访问某数据结构中的全部结点,而且每个结点只被访问一次。1. 遍历二叉树的定义DLR,LDR,LRD,DRL,RDL,RLD六种遍历形式。若规定先左后右,则归并成下述三种形式:DLR:先序遍历LDR:中序遍历LRD:后序遍历以图2.40中的
8、二叉树为例,三种遍历结果为:先序:ABCDEFG中序:CBDAEGF后序:CDBGFEA 2. 遍历算法 PROORDER(p)/先序遍历/1.if (pnil) then2.whrit(data(p); /访问根结点/3.PROORDER (L child(p);/遍历左子树/4.PROORDER (R child(p);/遍历右子树/5.returnBRBRARARARARARERFRA B C D E F G INORDER(p)/中序遍历/1.if (pnil) then2.INORDER(L,child(p); /遍历左子树/3. while(data(p); /访问根结点/4. I
9、NORDER(R,child(p); /遍历右子树/5ReturnBRBRARARARARARERFRC B D A E G FPOSTORDER(p)/后序遍历/1.if (pnil) then2.POSTORDER(L,child(p); /遍历左子树/3. POSTORDER(R,child(p); /遍历右子树/4. while(data(p); /访问根结点/5ReturnCOUNTLEFT(p,count) /p指向根结点,count为计数器,初值为01.if (pnil) then2.if (L child(p)=nil and (R child=nil)3. then coun
10、tcount +14. COUNTLEFT(L,child(p); 5. COUNTLEFT(R,child(p);6.return2.5. 4二叉树的应用1. 二叉排序树(1)定义二叉排序树或是空树,或是具有下述性质的二叉树:其左子树上所有结点的数据均小于根结点的数据值;右子树上所有结点的数据值均大于或等于根结点的数据值。左子树和右子树又各是一棵二叉排序树。图2.41所示就是一棵二叉排序树。在二叉排序树中,若按中序遍历就可以得到由小到大的有序序列,如图2.41中的二叉排序树,中序遍历可得到有序序列2,3,4,8,9,9,10,13,15,18,21。(2)二叉排序树的生成二叉排序树是一种动态
11、表结构,即二叉排序树的生成过程是不断地向二叉排序树中插入新的结点。对任意的一组数据元素序列R1,R2,Rn,要生成一棵二叉排序树的过程为: 令R1为二叉排序树的根结点。若R2R1,令R2为R1的左子树的根结点;否则R2为R1的右子树的根结点。R3,Rn结点的插入方法同上。二叉排序树插入算法如下:INSERBET(t,b) / 将数值b插入根结点指针为t的二叉排序树中,此函数返回值为指向根结点t的指针/1.if (t=nil) then /生成一个新结点,其数值域为b/2. GETNODE(t); data(t);L child(t)nil;R child(t)nil3.else if (bda
12、ta(t) then4. L child(t)INSERTBET(L child(t),b) /插入左子树/5. else 6.R child(t)INSERTBET(R child(t),b) /插入右子树/7.return(t) 图2.42所示为序列10,18,3,8,12,2,7,3 构成一棵二叉排序树的过程。(3)删除二叉排序树上的结点删除二叉排序树上的一个结点,也就是要在已排好序的序列中删除一个元素,因此要求删除一个结点后二叉树仍然是一棵二叉排序树。删除二叉排序树上结点过程较插入过程复杂,按照被删除结点在二叉排序树中的位置,可以有以下几种情况:被删除结点是叶子结点,则删除后不会影响整
13、个二叉排序树的结构,因此只需修改它双亲结点的指针即可。被删除结点P只有左子树PL或右子树PR,此时只要将左子树或右子树直接成为其双亲结点F的左或右子树即可,见图2.43(a)所示。若被删除结点P的左右子树均为非空。这是要循着P的左子树的根结点C,向右一直找到结点S,要求S的右子树为空。然后将S 的左子树改为结点Q的右子树,将S结点的数据域值取代P结点的数据域值,删除前后如图2.43(b)(c)所示。若被删除的结点为二叉排序树的根结点,则删除后应修改根结点指针。算法如下:DELNODE(t,p,f)/t为根结点指针,p指向被删除结点,f指向其双亲,当p=t时 f=nil/1.fag0/fag=0
14、需要修改F结点指针,fag=1不需修改/2.if (L child(p)=nil) then sR child(p)/p为叶子或左子树为空/3.else if (R child(p)=nil) then sL child(p) /p的右子树为空/4.else qp;sL child(p) /p的左右子树均为空/5. while (R child(s)nil) do 6. qs;sR child(p)寻找s结点/7. if (q=p) then L child(q)L child(s)8. else R child(q)L child(s). data(p)datea(s) /s值代替p值/10
15、. RET(s); fag1 /释放s结点/11.if (fag=0) then /修改F结点指针/12 if (f=nil) then ts /被删除结点为根结点/13.else if (L child(f)=p) then L child(f)s14. else R child(f)s15. RET(p) /释放结点p/16.return2. 哈夫曼树哈夫曼树又称最优树,是一类带权路径最短的树。(1)树的路径长度从树中一个结点到另一个结点之间的分支数目称为这对结点之间的路径长度。树的路径长度是从树根到每个结点的路径长度之和。路径长度用PL表示,图2.44中(a)(b)两棵树 的路径长度分别
16、为:(a) PL=0+1+2+2+3+4+5=17;(b) PL=0+1+1+24+3=13。在任何二叉树中,都存在如下情况:路径为0的结点至多只有1个;路径为1的结点至多只有2个; 路径为k的结点至多只有2k个。因此,n个结点的二叉树路径长度满足log21+log22+log23+log214+log215+log216+log217+log28+=0+1+1+2+2+2+2+3+从上述关系可知,具有最小路径长度的二叉树为完全二叉树。 (2)树的带权路径长度 结点带权路径长度为 该结点到树根之间的路径长度与结点上权值的乘积。树的带权路径长度为树中叶子结点的带权路径长度之和,记作其中wk为树中
17、每个叶子结点的权值,lk为每个叶子结点到根结点的路径长度。WPL最小的二叉树称作最优二叉树或哈夫曼树。例如图2.45中的三棵二叉树,都有4个叶子结点a,b,c,d,分别具有权值7,5,2,4,它们带权路径长度分别为: (a) WPL=7*2+5*2+2*2+4*2=36 (b) WPL=7*3+5*3+2*1+4*2=46(c) WPL=7*1+5*2+2*3+4*3=35其中以(c)为最小,可以验证(c)为哈夫曼树。 (3)哈夫曼树的构造 原则:权值越大的叶子离根结点的距离越近。 由给定的n个权值w1,w2,wn构成n棵二叉树的集合F=T1,T2,Tn,其中每棵二叉树只有一个权值为wi的根结
18、点,如图2.46(a)所示。 在F中选取两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和,如图2.46(b)所示。 将新的二叉树假如F中,去除原两棵根结点权值最小的树。 重复,两步骤,直到F中只含一棵树为止。这棵树 就是哈夫曼树,如图2.46(d)所示。在计算机上实现上述算法,首先要确定存储结构,由于哈夫曼树中没有度为1的结点,因此一棵有n个叶子结点的哈夫曼树共有2n-1个结点。结点采用数组型链表结构每个结点由4个数据域组成,即date:存放结点权值L child:左指针R child:右指针Prnt:双亲指针算法如下: HUF
19、FMAN(n,L child,R child,data,Prnt,w)/w1:n存放n个权值, L child1:m,R child1:m,data1:m, Prnt1:m,m=2n-1/1.for i=1 to n2. dataiwi;L child(i)0; R child(i)0 /初始化/3.end(i)4.for i=1 to (2*n-1) Prnti0/初始化/5.end(i)6for k=n+1 to (2*n-1)7. SELECT(k-1,i,j)/从data1:k-1中选出双亲为零的两个权值最小的下标i,j/ 8. datakdatai+datej9. L childki; R childkj;10. Prntik; Prntjk;11.end(k)12.return对应图2.46中哈夫曼树的存储空间的初始状态为图2.47(a),最终状态为图2.47(b)。(4)哈夫曼树的应用最佳判定算法分数段05960697079808990100比例0.050.150.400.300.10
限制150内