版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、数学与计算机学院计算机系数据结构程序设计报告平衡二叉树学生姓名:*学好:1004681028班级:计算机系102指导老师:*报告日期:2011/6/26目录1 .平衡二叉树31.1 平衡二叉树的定义.31.2 平衡二叉树的构造.31.3 平衡二叉树查找的分析.32 .程序功能33 .程序结构类型34 .程序函数45 .算法思想55.1 判断二叉树的旋转方法.55.2 平衡旋转处理.55.3 在平衡二叉树中插入元素.55.4 在平衡二叉树中删除元素.55.5 输由平衡二叉树树形.55.6 销毁平衡二叉树.56 .程序设计总结.97 .结束语108 .附录:程序清单10.平衡二叉树平衡二叉树的定义
2、平衡二叉树(BalancedBinaryTree或Height-BalancedTree)又称AVL树。它或者是一颗空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。若将二叉树上结点的平衡因子BF(BalancedFactor)定义为该结点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有结点的平衡因子之可能是-1、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。平衡二叉树的构造构造一颗平衡二叉树的过程就是将一颗空树从根结点起,逐步插入或删除结点并不断对此树进行平衡化。在构造平衡二叉树的过程中有插
3、入和删除两大操作。在树中进行插入和删除操作都可使树失去平衡,然而要让二叉排序树由不平衡转化为平衡,操作就是对二叉树进行旋转,旋转的过程将在算法思想中详细介绍。平衡二叉树查找的分析在平衡二叉树上进行查找的过程和二叉排序树相同,因此,在查找过程中和给定值进行比较的关键字个数不超过树的深度。因此,在平衡二叉树上进行查找的时间复杂度为O(logn).程序功能:创建二叉树、插入数据、本程序的功能就是将二叉排序树转变为平衡二叉树,其操作有删除数据、输出、销毁二叉树和退出。1创建二叉树2插入数据3删除数据4输出5销毁二叉树0退出请选择:.程序结构类型在本程序中主要用到两个结构类型:结构体和队列。二叉树是链式
4、存储结构,故用结构体来定义其结构。队列是用作输出二叉树的树形(层序输出)。.程序函数main()函数:(1)函数原形:voidmain()(2)功能:显示总菜单,调用子函数Create()函数:(1)函数原形:voidCreate(BSTree&T)(2)功能:实现二叉树的创建Insert()函数:(1)函数原形:voidInsert(BSTree&T)(2)功能:实现在二叉树中插入数据InsertAVL()函数:(1)函数原形:intInsertAVL(BSTree&T,inte,int&taller)(2)功能:插入结点,并将二叉树平衡化DeleteMenu
5、()函数:(1)函数原形:voidDeleteMenu(BSTree&T)(2)功能:实现在二叉树中删除数据DeleteA/L()函数:(1)函数原形:intDeleteAVL(BSTree&T,inte,int&shorter)(2)功能:删除结点,并将二叉树平衡化Delete()函数:(1)函数原形:intDelete(BSTree&p)(2)功能:实现删除结点Search(尚数:(1)函数原形:voidSearch(BSTree&T,inte,intkey)(2)功能:在树中查找和关键字相等的结点R_Rotate()函数:(1)函数原形:voidR
6、_Rotate(BSTree&p)(2)功能:对以*p为根结点的子树进行右旋平衡处理L_Rotate()函数:(1)函数原形:voidL_Rotate(BSTree&p)(2)功能:对以*p为根结点的子树进行左旋平衡处理RightBalance()S数:(1)函数原形:intRightBalance(BSTree&T)(2)功能:对以指针T所指结点为根的二叉树作右平衡旋转处理LeftBalance()函数:(1)函数原形:intLeftBalance(BSTree&T)(2)功能:对以指针T所指结点为根的二叉树作左平衡旋转处理Output()函数:(1)函数原形
7、:voidOutput(BSTreeT)(2)功能:将二叉树按中序和层序输出Inordertraverse()函数:(1)函数原形:voidInordertraverse(BSTreeT)(2)功能:将二叉树按中序输出Depth()函数:(1)函数原形:voidDepth(BSTreep,intn,int&num)(2)功能:求二叉树的深度Levelordertraverse(尚数:(1)函数原形:intLevelordertraverse(Stack&Q)(2)功能:将二叉树按层序输出Initstack()函数:(1)函数原形:intInitstack(Stack&Q
8、)(2)功能:构造一个空队列Push()S数:(1)函数原形:intPush(Stack&Q,BSTreee)(2)功能:插入元素e为新的队尾元素Pop()函数:(1)函数原形:intPop(Stack&Q,BSTree&q)(2)功能:删除对头元素Destroy(尚数:(1)函数原形:voidDestroy(BSTree&T)(2)功能:将队列销毁.算法思想判断二叉树的旋转方法在一颗平衡二叉树中插入或删除一个结点后,若二叉树失去平衡,则需将二叉树进行平衡化处理,简而言之,就是对不平衡的二叉树进行旋转处理。假设在二叉排序树中插入或删除结点而失去平衡的最小子树根结
9、点的指针为T(即T是离插入或删除结点最近,且平衡因子绝对值超过1的祖先结点),指针p指向结点T的左子树的根结点,指针q指向结点T的右子树的根结点,则判断方法如下:(1)若结点T的平衡因子为2,结点p的平衡因子为1,则需对结点T进行单向右旋平衡处理;(2)若结点T的平衡因子为-2,结点p的平衡因子为-1,则需对结点T进行单向左旋平衡处理;(3)若结点T的平衡因子为2,结点p的平衡因子为-1,则需先对结点p进行单向左旋平衡处理,再对结点T进行单向右旋平衡处理,将这两步简称为对结点T进行双向旋转(先左后右)平衡处理;(4)若结点T的平衡因子为-2,结点p的平衡因子为1,则需先对结点p进行单向右旋平衡
10、处理,再对结点T进行单向左旋平衡处理,将这两步简称为对结点T进行双向旋转(先右后左)平衡处理;平衡旋转处理假设由于在二叉排序树上插入或删除结点而失去平衡的最小子树根结点的指针为T(即T为里插入结点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行平衡处理有如下4种情况:(1)单向右旋平衡处理:若指针p指向以*T为根的左子树的根结点,将*p的右子树作为*T的左子树,再将以*T为根的树作为*p的右子树,如图(a)所示。(2)单向左旋平衡处理:若指针p指向以*T为根的右子树的根结点,将*p的左子树作为*T的右子树,再将以*T为根的树作为*p的左子树,如图(b)所示。(3)双向旋转(先左后右)
11、平衡处理:若p指向以*T为根的左子树的根结点,q以*p为根的右子树的根结点,则先将以*p为根结点的树进行单向左旋,再将以*q为根结点的树进行单向右旋,如图(c)所示。图(4)双向旋转(先右后左)平衡处理:若p指向以*T为根的右子树的根结点,q以*p为根的左子树的根结点,则先将以*p为根结点的树进行单向右旋,再将以*q为根结点的树进行单向左旋,如图(d)所示。2图(d)在平衡二叉树BBST中插入元素在平衡的二叉排序树上插入一个新的数据元素e:(1)若BBST为空树,则插入一个数据元素e的新结点作为BBST的根结点,树的深度增1;(2)若e的关键字和BBST的根结点的关键字相等,则不进行插入;(3
12、)若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加(+1)时,分别就下列不同情况处理:BBST的根结点的平衡因子为-1(右子树的深度大于左子树的深度):则将根结点的平衡因子更改为0,BBST的深度不变;BBST的根结点的平衡因子为0,(左、右子树的深度相等):则将根结点的平衡因子更改为1,BBST的深度增1;BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):若BBST的左子树的平衡因子为1,则需进行单向右旋平衡处理,并且在右旋处理之后,将根结点和其右子树根结点的平衡因子更
13、改为0,树的深度不变;若BBST的左子树根结点的平衡因子为-1,则需进行先向左、后先向右的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左、右子树根结点的平衡因子,树的深度不变;(4)若e的关键字大于BBST的根结点的关键字,而且BBST的右子树不存在和e有相同关键字的结点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理:BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):则将根结点的平衡因子更改为0,BBST的深度不变;BBST的根结点的平衡因子为0,(左、右子树的深度相等):则将根结点的平衡因子更改为-1,BBST的深度增1;
14、BBST的根结点的平衡因子为-1(右子树的深度大于左子树的深度):若BBST的左子树的平衡因子为-1,则需进行单向左旋平衡处理,并且在左旋处理之后,将根结点和其左子树根结点的平衡因子更改为0,树的深度不变;若BBST的左子树根结点的平衡因子为1,则需进行先向右、后先向左的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左、右子树根结点的平衡因子,树的深度不变;平衡二叉树中删除元素假设在平衡二叉树上删除结点为*p(指向结点的指针为p),其双亲结点为*f(结点指针为f),且不失一般性,可设*p是*f的左孩子:(1)若*p结点为叶子结点,则直接将*p结点删除,如图(e)所示。图(e)(2)若*p
15、结点只有左子树或者只有右子树,此时只要令*p的左子树或右子树成为其双亲结点*f的左子树,如图(f)所示;图(2)若*p结点的左子树和右子树均不空,则令*p的直接前驱代替*p,然后再从二叉排序树中删去它的直接前驱,如图(g)所示;在上述三种删除*p结点的处理后,若二叉树仍然平衡,则只需修改*f结点的平衡因子;否则,则需从*p结点回溯到根结点,找到回溯途中遇到的不平衡结点,并将其平衡化;将删除结点后不平衡树平衡化的具体处理方法如下:设p为回溯至根结点的路径上的某一结点结点p的平衡因子为0,若删除结点为p结点左子树上的结点,则将结点p的平衡因子改为-1,并相应将树平衡化;若删除结点为p结点右子树上的
16、结点,则将结点p的平衡因子改为1,并相应将树平衡化。无论删除结点为p结点左子树或右子树上的结点,都不需要再向根结点回溯,平衡处理结束;结点p的平衡因子为1,若删除结点为p结点左子树上的结点,则将结点p的平衡因子该为0,再从结点p向根结点回溯;若删除结点为p结点右子树上白结点,设q指向p的左子树的根结点,则需将结点p进行单向右旋处理,并相应修改各结点的平衡因子,再从结点p向根结点回溯;结点p的平衡因子为-1,若删除结点为p结点左子树上的结点,设q指向p的右子树的根结点,则需将结点p进行单向左旋处理,并相应修改各结点的平衡因子,再从结点p向根结点回溯;若删除结点为p结点右子树上的结点,则将结点p的
17、平衡因子该为0,再从结点p向根结点回溯;特别需要注意的是,在平衡二叉树中删除一个结点后使不平衡根结点的平衡因子变为2或-2,根结点的左或右孩子的平衡因子为0,此时需将根结点进行单向右或左旋处理,然而旋转处理后的树的深度不变,如图(h)所示。图(h)输出平衡二叉树树形将一颗平衡二叉树按树形输出,要用到队列,并且将此平衡二叉树当做满二叉树,孩子结点为空的用空字符代替。首先,应先求出二叉树的深度n,根据完全二叉树的性质知,第n层上的结点数至多为2n-1。此时,便可知道每层上应输出的空格数,并可以控制每层上结点之间的间距。此外,还要控制换行,记录输出的结点数num,若num等于i层的总结点数2i-1则
18、换行。若树不为空,则将根结点插入到队列中,接着将根结点从队列中删除并输出,再把根结点的左、右孩子插入到队列中,若孩子结点为空则用空字符代替,重复上述操作,直到当num等于n层总结点数2n-1,则结束输出。销毁平衡二叉树销毁平衡二叉树就是将二叉树中的每一个结点用free()函数释放,其具体过程采用递归:将平衡二叉树的根结点的指针T传到销毁函数,如果*T结点的左孩子不为空,则将*T结点的左子树的根结点进行递归,直到结点的左孩子为空;再判断结点的右孩子是否为空,若不为空则将结点的右子树的根结点进行递归,直到结点的右子树为空;最后将结点的指针赋为空指针。.程序设计总结将一颗二叉排序树转变为平衡二叉树并
19、将平衡树按树形输出的算法,主要操作就是插入、删除和输出。本人在编写插入算法,经过陈老师的讲解和课后的思考,根据书本上的算法编写完成。然而,在二叉树中删除结点,本人是在网上以及图书馆书籍上查找的。很令人失望的是,网上和书籍里对于在二叉树中删除结点再将其平衡化的算法思想介绍很少,甚至有些书籍上根本就没提及过。看着做的一点笔记,本人还是很是不知所措,不懂其算法思想,经过三天的思索,终于有些头绪,尝试着编写,尽管失败了很多次,但总算勉强写出了算法。(我所编写的算法可能和书籍中讲解的不同,只是换了一种实现方法。)至于将二叉树按树形输出,是在陈老师的指导下写出的,陈老师告诉我算法思想,之后就在思想的指导下
20、完成了算法。能完成这个程序,我还是感到挺高兴的,在今后我也会一如既往,认真努力学习,不断提升自己,实现自己的理想。.结束语在此,我很是感谢陈老师,他在我学习的途中给了我很多的帮助,让我懂得很多东西,学会很多,真心感谢他。同时,我也要对平时帮助我的同学表示感谢。在我人生的道路中,很多人在我失意时帮我走出阴霾,感谢他们。.附录:程序清单#include<stdio.h>#include<stdlib.h>#include<math.h>defineOK1defineERROR0defineLH1defineEH0defineRH-1typedefstructBS
21、TNodeintdata;intbf;structBSTNode*lchild,*rchild;BSTNode,*BSTree;typedefstructBSTreep;elem,*Elem;typedefstructElembase;Elemtop;Stack;inth,num,m,k,t,key=0;BSTreew;voidCreate(BSTree&T);voidInsert(BSTree&T);intInsertAVL(BSTree&T,inte,int&taller);voidR_Rotate(BSTree&p);voidL_Rotate(BS
22、Tree&p);intLeftBalance(BSTree&T);intRightBalance(BSTree&T);voidDeleteMenu(BSTree&T);intDeleteAVL(BSTree&T,inte,int&shorter);intDelete(BSTree&p);voidSearch(BSTree&T,inte,intkey);voidOutput(BSTreeT);voidInordertraverse(BSTreeT);voidDepth(BSTreep,intn,int&num);intLev
23、elordertraverse(Stack&Q);intInitstack(Stack&Q);intPush(Stack&Q,BSTreee);intPop(Stack&Q,BSTree&q);voidDestroy(BSTree&T);voidmain()inta=1,flag=0;BSTreeT=NULL;while(a)system("cls");printf("nnnnntttt1创建二叉科nnnn");printf("tttt2-插入数据nnnn");printf("
24、tttt3一删除数据nnnn");printf("tttt4-输出nnnn");printf("tttt5销毁二叉nnnn");printf("tttt0-退出nn");if(!flag)printf("nnnn请选择:");elseprintf("nnnn你的输入有误,请重新输入:");flag=0;scanf("%d",&a);switch(a)case1:system("cls");Create(T);break;case2:sys
25、tem("cls");Insert(T);break;case3:system("cls");DeleteMenu(T);break;case4:system("cls");if(T)Output(T);elseprintf("此二叉树为空树");printf("nnn按Enterf");getchar();getchar();)break;case5:system("cls");Destroy(T);printf("已将此二叉树销毁nnnn");prin
26、tf("nnn按Enterf");getchar();getchar();case0:system("cls");printf("nnnnnnnnnntttttTHANKSnnnnnnnnnnnn");break;default:flag=1;break;)voidCreate(BSTree&T)inta=1,s,taller=false;while(a)printf(“请输入数据(0结束):");scanf("%d",&a);if(a)s=InsertAVL(T,a,taller);if
27、(!s)printf("%d已存在二叉树中",a);)printf("nn");)voidInsert(BSTree&T)inta,s,taller=false;printf("请输入数据:");scanf("%d",&a);dos=InsertAVL(T,a,taller);if(s)printf("nn%d已插入到二叉树中",a);elsesystem("cls");printf("%d已存在二叉树中,请重新输入:”,a);scanf("
28、;%d",&a);)while(!s);printf("nnnnnnn按Enterf");getchar();getchar();intInsertAVL(BSTree&T,inte,int&taller)if(!T)T=(BSTree)malloc(sizeof(BSTNode);if(!T)exit(-1);T->data=e;T->bf=EH;T->lchild=T->rchild=NULL;taller=true;elseif(e=T->data)taller=false;return0;elseif(
29、e<T->data)if(!InsertAVL(T->lchild,e,taller)return0;if(taller)switch(T->bf)caseLH:LeftBalance(T);taller=false;break;caseEH:T->bf=LH;taller=true;break;caseRH:T->bf=EH;taller=false;break;elseif(!InsertAVL(T->rchild,e,taller)return0;if(taller)switch(T->bf)caseLH:T->bf=EH;talle
30、r=false;break;caseEH:T->bf=RH;taller=true;break;caseRH:RightBalance(T);taller=false;break;return1;voidDeleteMenu(BSTree&T)inta,shorter=false,s;printf("请输入要删除的数据:");scanf("%d",&a);dos=DeleteAVL(T,a,shorter);ifprintf("nn已将从二叉树中删除",a);elseif(key)DeleteAVL(T,key,
31、shorter);Search(T,a,key);printf("nn已将d从二叉树中删除",a);elsesystem("cls");printf("%d不在此二叉树中,请重新输入:",a);scanf("%d",&a);while(!s&&!key);key=0;printf("nnnnnnn按Enterf");getchar();getchar();intDeleteAVL(BSTree&T,inte,int&shorter)ints;if(!T)s
32、horter=0;return0;elseif(T->data=e)s=Delete(T);if(!s)return0;elseshorter=1;return1;elseif(e<T->data)if(!DeleteAVL(T->lchild,e,shorter)return0;if(shorter)switch(T->bf)caseLH:T->bf=EH;shorter=1;break;caseEH:T->bf=RH;shorter=0;break;caseRH:shorter=RightBalance(T);break;)elseif(!Dele
33、teAVL(T->rchild,e,shorter)return0;if(shorter)switch(T->bf)caseLH:shorter=LeftBalance(T);break;caseEH:T->bf=LH;shorter=0;break;caseRH:T->bf=EH;shorter=1;break;)return1;)intDelete(BSTree&p)BSTreeq,s;if(!p->rchild)q=p;p=p->lchild;free(q);)elseif(!p->lchild)q=p;p=p->rchild;fr
34、ee(q);)elseq=p;s=p->lchild;while(s->rchild)q=s;s=s->rchild;)key=s->data;return0;)return1;)voidSearch(BSTree&T,inte,intkey)if(T->data=e)T->data=key;elseif(e<T->data)Search(T->lchild,e,key);elseSearch(T->rchild,e,key);)voidR_Rotate(BSTree&p)BSTreelc;lc=p->lchil
35、d;p->lchild=lc->rchild;lc->rchild=p;p=lc;)voidL_Rotate(BSTree&p)BSTreerc;rc=p->rchild;p->rchild=rc->lchild;rc->lchild=p;p=rc;)intRightBalance(BSTree&T)BSTreerc,ld;rc=T->rchild;switch(rc->bf)caseLH:ld=rc->lchild;switch(ld->bf)caseLH:T->bf=EH;rc->bf=RH;br
36、eak;caseEH:T->bf=rc->bf=EH;break;caseRH:T->bf=LH;rc->bf=EH;break;)ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);break;caseEH:T->bf=RH;rc->bf=LH;L_Rotate(T);return0;break;caseRH:T->bf=rc->bf=EH;L_Rotate(T);break;)return1;)intLeftBalance(BSTree&T)BSTreelc,rd;lc=T->lchild;switch(lc->bf)caseLH:T->bf=lc->bf=EH;R_Rotate(T);break;caseEH:T->bf=LH;lc->
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 科普教育教研工作总结与成果
- 打柜子装修合同模板
- 加盟合伙创业合同模板
- 单位楼房翻新合同模板
- 新冠疫情下的产前检查方案
- 定制家具责任合同模板
- 杭州礼仪庆典合同模板
- 北京社保合同模板
- 上门收车合同模板
- 世纪宏二手房合同模板
- 期中模拟卷(含答案)2024-2025学年浙教版七年级数学上册
- 2024年区卫生健康系统公开招聘大学生村医考试题及答案
- 廉洁纪律十道题
- 高三英语 时政类语篇型填空专项训练
- 八年级生物上册 5.14.3《神奇的微生物》说课稿 (新版)苏教版
- 2024年度信息化教学校本研修实施方案
- 2024年湖南省长沙市中考历史试卷真题(含答案解析)
- 2024年中移建设限公司安徽分公司社会招聘12人高频难、易错点500题模拟试题附带答案详解
- 2024秋期国家开放大学《政治学原理》一平台在线形考(形考任务二)试题及答案
- 变配电运维知识考试题(含参考答案)
- 摩托车维修技术考核试卷
评论
0/150
提交评论