实验四 平衡二叉树演示Word文档格式.docx
- 文档编号:21104221
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:43
- 大小:153.80KB
实验四 平衡二叉树演示Word文档格式.docx
《实验四 平衡二叉树演示Word文档格式.docx》由会员分享,可在线阅读,更多相关《实验四 平衡二叉树演示Word文档格式.docx(43页珍藏版)》请在冰豆网上搜索。
5//层次遍历输出第二个树的结构图
t2//操作树名
3//插入元素操作
1//插入元素个数
7//依次插入元素
5//层次遍历输出树的结构图
4//删除元素操作
1//删除元素个数
7//依次删除元素
6//合并两个树操作
t1t2//操作树名
2//查询元素操作
5//需要查询的元素(该元素树中存在)
11//需要查询的元素(该元素树中不存在)
7//删除二叉平衡树操作
2//查询操作
t1//操作树名(会提示该树不存在,说明删除树成功)
0//退出程序
2.概要设计
2.1抽象数据类型
需要定义一个树的结构类型,其中包含数据类型,它的左右孩子指针,以及平衡因子,平衡因子的取值为-1,0,1三种,分别对应树的右边高(RH),平衡(EH)和左边高(LH)三种情形,通过平衡因子的判别,来调整树的高度使其达到平衡;
另外需要用到双向链表的数据结构,以及队列的数据结构。
2.2主程序流程及各模块之间的调用关系
3.详细设计
3.1存储结构实现
typedefstructType{//数据类型结构
floatnum;
}Type;
/*平衡树结构声明*/
typedefstructAVLTree{//二叉平衡树结构体声明
intbf;
//结点的平衡因子
structTypedata;
//结点数据
structAVLTree*lchild,*rchild;
//左右孩子
}AVLTree,*AVL;
/*队列结构声明*/
typedefstructQNode{//队列
AVLtree;
structQNode*next;
}QNode,*QP;
typedefstruct{
QPfron;
QPrear;
}LinkQ;
/*双向链表结构声明*/
typedefstructLNode{//链表
AVLt;
chartree_name[NAME_LENGTH];
structLNode*prior,*next;
}LNode,*Link;
3.2负责模块的伪码算法
(1)voidLeftBalance(AVL&
t){//左部平衡化处理
l=t->
lchild;
switch(l->
bf){
//检查T的左子树平衡度,并作相应的平衡处理
caseLH:
//新节点插入在T的左孩子的左子树上,做单右旋处理
调整平衡因子;
R_Rotate(t);
break;
caseEH:
//deleteAVL需要,insertAVL用不着
caseRH:
//新插入节点在T的左孩子的右子树上,做双旋处理
lr=l->
rchild;
switch(lr->
}
L_Rotate(t->
lchild);
R_Rotate(t);
}
(2)voidRightBalance(AVL&
t){//右部平衡化处理
r=t->
switch(r->
//新节点插在T的右孩子的右子树上,要做单左旋处理
L_Rotate(t);
//新节点插在T的右孩子的左子树上,要做双旋处理
rl=r->
switch(rl->
caseEH:
R_Rotate(t->
rchild);
L_Rotate(t);
(3)voidR_Rotate(AVL&
t){//以T为根节点的二叉排序树进行右旋转
//将t的左孩子给l
t->
lchild=l->
//将l的右孩子给t的左孩子指针
l->
rchild=t;
//将t变成l的右孩子
t=l;
//指向新的节点l
(4)voidL_Rotate(AVL&
t){//以T为根节点的二叉排序树进行左旋转
rchild=r->
r->
lchild=t;
t=r;
(5)intDeleteTree(AVL&
t,Typee,int&
shorter){
//平衡二叉树的结点删除
if(t==NULL){//不存在该元素
return0;
//删除失败
elseif(e==t->
data){//找到元素结点
q=NULL;
if(t->
lchild==NULL){
//左子树为空将右子树接上,删除该点;
shorter=1;
elseif(t->
rchild==NULL){
//右子树为空将左子树接上,删除该点;
else{//左右子树都存在
q=t->
while(q->
rchild){
//找到要删除结点t的左孩子的最右孩子q
q=q->
data=q->
data;
//把q的值给t
DeleteTree(t->
lchild,q->
data,shorter);
//在左子树中递归删除前驱结点。
即查找q的值
if(shorter){//如果树变矮了,调节平衡因子
switch(t->
t->
bf=EH;
shorter=1;
bf=RH;
shorter=0;
rchild->
bf==EH)
shorter=0;
else
RightBalance(t);
//右平衡处理
break;
elseif(e<
data){//左子树中继续查找
if(!
DeleteTree(t->
lchild,e,shorter)){
if(shorter){
else{//右子树中继续查找
rchild,e,shorter)){
lchild->
LeftBalance(t);
//左平衡处理
bf=LH;
return1;
(6)intMergeTree(AVL&
t1,AVL&
t2){//将树t2合并到t1上
while(t2!
=NULL){//t2不为空时
InsertTree(t1,t2->
data,taller);
//将t2中元素插入t1
DeleteTree(t2,t2->
//将插入后的t2中元素删除
(7)constintPrintTreeStructure(AVLt){
//利用层次遍历,输出树的形状
t){return0;
}//树不存在,返回
InitQ(q);
//建立空队列
while
(1){//循环输出树中元素
i++;
//第i个元素
num=0;
j=1;
while(j<
=i){
num++;
//num为记层标志,记录当前T所在层数
j=2*j;
if(t!
=NULL){
cout当前元素;
EnQ(q,t->
//将左右孩子入队列
if(j==i+1){
cout<
<
endl;
//换行
lchild==NULL&
&
//T为空时进行判断,当平衡树中出现层数不同的空结点时,终止输出
level){
//首次出现两个孩子都空的结点,将其孩子的层数赋给level
level=num+1;
else{
EnQ(q,NULL);
//若该点为空,则它的孩子也为空,入队列
if(level&
level+2==num){
//当遇到空结点,并且它的层数比标记层数大2时,结束输出
else{cout<
"
*"
;
}//用*代表空
DeQ(q,t);
//出队列
}//while
4.调试分析
4.1问题分析与解决方法
平衡二叉树中最难处理的是平衡问题,如何保证所创建的树是一个平衡树是关键问题。
考虑可以通过递归调用的方式,通过层层递归,来调节各层节点的平衡因子。
在调试过程中经常出现平衡因子数值不对的问题,经过仔细检查,发现是某些部分的代码不能适用于全部的可能情形,当一种新情形出现时,就会产生错误。
经过不断的调试和改进,对这部分代码添加if判断,来区分各种不同的情形,进行不同的平衡因子调节和平衡化操作,从而解决了这一问题,通过目前测试来看,程序对于各种数据都有很好的稳定性。
在直观输出树的结构图和平衡因子的算法调试中,也出现了各种问题
,例如没按预想换行,没有按预想结束输出以及过早结束输出等问题,经过不断地改进和尝试,最后采用了标记层数法,即当首次出现一个既没有左孩子也没有右孩子的结点时,将它孩子的层数标记下来,之后,如果出现一个空的结点,而它的层数比标记层数大2时,就可以结束循环,这是利用了平衡二叉树的特性。
4.2算法的时空分析
(1)平衡化操作
时间复杂度:
仅需要进行简单的判断,因此为
空间复杂度:
不需要开辟空间,为
(2)删除结点操作
主要时间花费在查找需要删除的结点和找该结点的中序前驱上,因此时间复杂度为
(3)合并树
需要在t2中找到插入位置,时间复杂度为
直接合并到t1上,不另开辟空间
(4)层次遍历树
需遍历全树,且进行入队列、出队列操作,大约为
需借助队列和标记,因此需要一定的空间量,不超过
4.3算法的改进设想
能否在查找删除节点和合并树的操作上进行算法的优化改进,使得查找效率和合并效率更高。
4.4经验和体会
递归调用对于平衡树的平衡调节具有非常重要的作用,这大大减少了代码量,并且使得代码更加简洁。
然而递归调用的过程却是非常
复杂不容易理解的,稍不留神就有可能出现错误的调用,由于是层层递归,所以对函数运行情况的跟踪并不容易,十分容易出现错误。
因此,为了减少错误,应当在编写前弄清楚整个函数所要实现的功能,并且尽量将代码写的规范,以便于调试的时候进行修改。
5.使用说明
本程序有菜单和提示语句,按照操作提示进行操作即可。
要求输入数量数据时,必须输入小于32767的正整数。
插入结点的数据可以是小数。
本程序具有非法输入检测功能,但是请勿输入不合规则的数据,以免出现意想不到的错误。
6.测试结果(截屏)
(1)原树t2的结构图:
(2)t2删除结点7后,层次遍历输出树的结构图:
(3)树t1的结构图:
(4)将t2合并到t1后,输出树的结构图:
7.附录
7.1个人负责模块的程序代码
voidLeftBalance(AVL&
AVLl,lr;
bf=l->
lr->
voidRightBalance(AVL&
AVLr,rl;
bf=r->
rl->
voidR_Rotate(AVL&
AVLl;
//p指向新的根节点
voidL_Rotate(AVL&
AVLr;
intDeleteTree(AVL&
shorter){//平衡二叉树的结点删除
elseif(e.num==t->
data.num){//找到元素结点
AVLq=NULL;
lchild==NULL){//左子树为空
q=t;
t=t->
deleteq;
rchild==NULL){//右子树为空
rchild){//找到要删除结点t的左孩子的最右孩子q
data.num=q->
data.num;
elseif(e.num<
data.num){//左子树中继续查找
intMergeTree(AVL&
inttaller,shorter;
#include"
H.h"
constintPrintTreeStructure(AVLt){//利用层次遍历,输出树的形状
inti=0,level=0,j,num;
LinkQq;
while
(1){
data.num<
("
bf<
)"
rchild==NULL){//T为空时进行判断,当平衡树中出现层数不同的空结点时,终止输出
level){//首次出现两个孩子都空的结点,将其孩子的层数赋给level
7.2程序全部代码
/*H.h文件*/
#ifndefH_H_INCLUDED
#defineH_H_INCLUDED
#include<
stdlib.h>
string.h>
stdio.h>
iostream>
usingnamespacestd;
#def
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验四 平衡二叉树演示 实验 平衡 二叉 演示
![提示](https://static.bdocx.com/images/bang_tan.gif)