数据结构程序设计报告平衡二叉树.docx
《数据结构程序设计报告平衡二叉树.docx》由会员分享,可在线阅读,更多相关《数据结构程序设计报告平衡二叉树.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构程序设计报告平衡二叉树
数学与计算机科学学院数据结构程序设计报告
平衡二叉树
学生姓名:
学号:
班级:
指导老师:
报告日期:
1.题目与要求
1).问题的提出
编写已个平衡二叉树,主要是对插入一个元素导致树不平衡的情况进行平衡化处理以及相关的处理。
2)设计的知识点
队列的插入,删除,二叉树的建立于销毁,平衡树的平衡化,以及C语言中基础应用于结构等。
3)功能要求
(1).通过不断插入的方式创建一棵平衡二叉树,包括输入结点的关键字和相关信息。
(2)按要求输出创建的平衡二叉树结点,包括顺序(中序)输出和按层次输出。
(3)插入新增的结点,若结点不存在则插入平衡二叉树,并进行相关调整。
(4)销毁二叉树。
(5)退出
菜单界面如下:
2.功能设计
算法设计
选择创建平衡二叉树后,利用循环不断插入结点,并进行调整,当输入节点为0时停止进入菜单界面。
在平横二叉树排序树BSTree上插入一个新的数据元素e的递归算法可如下描述:
(1)若BSTree为空树,则插入一个数据元素为e的新结点作为BSTree的根结点,树的深度增1;
(2)若e的关键字和BSTree的根节点的关键字相等,则不进行插入;
(3)若e的关键字小于BSTree的根结点的关键字,而且在其左子树中不存在和e形同的关键字的结点,则将e插入在其左子树上,并且当插入之后的左子树的深度加1时,分别就下列不同情况处理之:
a.BSTree的跟结点的平衡因子为-1(右子树的深度大于左子树的深度):
则将跟结点的平衡因子更改为0,BBST的深度不变;
b.BBST的根结点的平衡因子为0(左,右子树的深度相等):
则将根结点的平衡因子更改为1,BBST的深度增1;
c.BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):
若BBST的左子树根结点的平衡因子为1,则需进行向左旋平衡处理,并且在右旋之后,将根节点和其右子树根节点的平衡因子更改为0,树的深度不变;
若BBST的左子树根结点的平衡因子为-1,则需进行向左,向右的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左右子树的平衡因子,数的深度不变;
(4)若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同的关键字的的节点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。
3.详细设计
1)结点类型定义:
typedefstructElemType{
KeyTypeKey;//键值类型
charinfo[20];
}ElemType;
TypedefstructBSTNode{
ElemTypedata;
intbf;//结点的平衡因子
structBSTNode*lchild,*rchild;//左右孩子指针
}BSTNode,*BSTree;
2)调平二叉树(左右调平方式大体雷同,之具体写出其中一种调平方式)
if(插入元素与当前根元素相等)
{
printf("已存在相同关键字的结点\n");
}
if(插入元素小于当前根元素))
{
if(插入新结点不成功)
return0;
if(插入成功)
switch(查看根的平衡因子)
{
case+1:
进行左平衡处理;
{
检查*T的左子树的平衡度,并作相应平衡处理
{
case+1:
令根及其左孩子的平衡因子为0;
做右平衡处理;
{
BTreelc;
lc指向的结点左子树根结点;
rc的右子树挂接为结点的左子树;
lc的右孩子为原结点;
原结点指向新的结点lc;
}
break;
case-1:
rd指向*T的左孩子的右子树根
switch(查看右孩子平衡因子)
{
case+1:
根的平衡因子为-1;
根左孩子的平衡因子为0;
break;
case0:
令根和根左孩子的平衡因子为0;
break;
case-1:
根平衡因子为0;
根左孩子平衡因子为1;
break;
}
根右孩子的平衡因子为0;
对*T的左子树作左旋平衡处理;
对*T作右旋平衡处理;
}
break;
case0:
令根的平衡因子为+1;
break;
case-1:
令根的平衡因子为-1;
break;
}
}
运行情况:
3)输出:
(1)中序输出
采用递归算法对二叉树进行遍历。
if(结点不为空)
{
If(遍历左孩子成功)
If(遍历结点成功)
If(遍历右孩子成功)
返回真
返回假
}
else(结点为空)
返回假
(2)按层次输出
根据队列先进先出的特点,先将第一层结点进队a,对其出出队并输出,同时将其不为空的孩子指针入另一队列b,当a为空时,队b进行出对并输出处理,将结点的不为空的左右孩子入队a,直到b为空............如此直到两队均为空。
根节点入队;
While(a,b不同时为空)
{
If(i为奇数)
{
While(a队不空)
{
a中结点出队并输出;
If(左孩子不空)
左孩子入队b;
If(有孩子不空)
右孩子入队b;
}
}
If(i为偶数)
{
While(b队不空)
{
b中结点出队并输出;
If(左孩子不空)
左孩子入队a;
If(有孩子不空)
右孩子入队a;
}
}
I++;//同时记录树的深度
}
具体的运行情况如下
4)销毁二叉树
销毁二叉树的算法根据递归遍历而来,算法大体相识。
If(根节点不空)
{
If(左子树不空)
销毁左子树;
If(右子树不空)
销毁右子树;
销毁相对根节点;
根节点赋空;//留下来以便再次创建二叉树时使用
}
注意:
必须先销毁左右子树,否则先销毁根节点后,无法找到左右孩子指针。
5)退出
退出时询问是否确认退出,确认则退出,否则返回到主菜单
4.程序代码设计
(1)函数原形:
voidCreatBalanceTree(BSTree&T);
功能:
调用插入函数,利用循环来进行平衡二叉树的创建。
当输入的键值为0时停止输入。
说明:
在输入相关信息时,需要清空缓存区的回车键值。
(2)函数原形:
intInsertAVL(BSTree&T,ElemTypee);
功能:
插入一个结点,如果待插入的结点键值已存在与树中,则返回。
否则找到插入位置,插入。
若因插入结点后使二叉树失去平衡。
则插入后根据平衡因子调用相关的函数进行平衡化处理。
说明:
这是一个递归的过程。
(3).函数原形:
voidR_Rotate(BSTree&p);
功能:
对以*p为根的二叉树进行右旋处理,处理后的p指向根节点。
(4).函数原形:
voidL_Rotate(BSTree&p);
功能:
对以*p为根的二叉树进行左旋处理,处理后的p指向根节点。
(5).函数原形:
voidLeftBalance(BSTree&T);
功能:
对以指针T所指结点的二叉树进行左平衡旋转处理,本算法结束时。
T指向新的根节点。
调用了左旋和右旋函数。
(6).函数原形:
voidRightBalance(BSTree&T);
功能:
对以指针T所指结点的二叉树进行右平衡旋转处理,本算法结束时。
T指向新的根节点。
调用了左旋和右旋函数。
(7).函数原形:
intPrint_Mid(BSTreeT);
功能:
采用递归的方式对二叉树进行中序输出。
(8).函数原形:
voidDestory(BSTree&T);
功能:
此算法和递归遍历十分相识。
采用递归进行销毁。
说明:
销毁的过程中,必须先销毁左右子树,再销毁根结点,否则先销毁根结点后,左右孩子指针无法找到。
销毁后T赋空,预留下来进行下一次的创建。
(9).函数原形:
intVisit(BSTreeT);
功能:
输出结点的关键值。
成功则返回真。
(10).函数原形:
intWideTraverse(BSTreeT);
功能;进行平衡二叉树的层次输出,同时可以计算出数的深度。
5.课程设计总结
(1)调试情况:
由于指针处理不当,调试过程中经常出现指针出错的情况,导致程序终止,经过仔细修改后才得以改正。
在程序整体设计过程中,由于忽视&的作用而导致程序无法正常运行。
(2).感想:
通过此次课程设计,让我对数据结构的重要学习内容有了更加深刻的了解,同时也意识到自己还存在很大的不足,还有很多的知识需要完善。
在编程的过程中错误时在所难免的,处了要修改错误外还有了解错误的原因。
而不是仅仅修改而已。
6.参考文献
[1]数据结构(C语言版)严蔚宽吴伟民编著
[2]C语程序设计白燕尹业安编著
7.附录:
程序清单
#include
#include
#defineERROR0
#defineTRUE1
#defineOK1
#defineFALSE0
#defineLH1
#defineRH-1
#defineEH0
#defineEQ(a,b)((a)==(b))
#defineLT(a,b)((a)<(b))
#defineLQ(a,b)((a)<=(b))
typedefintKeyType;
typedefstructElemType
{
KeyTypeKey;
charinfo[20];
}ElemType;
typedefstructBSTNode
{
ElemTypedata;
intbf;
structBSTNode*lchild,*rchild;
}BSTNode,*BSTree;
typedefstructQNode
{
BSTreee;
structQNode*next;
}QNode,*QNodeP;
typedefstruct
{
QNodePfront;
QNodePrear;
}LinkQueue;
voidCreatBalanceTree(BSTree&T);
voidR_Rotate(BSTree&p);
voidL_Rotate(BSTree&p);
intInsertAVL(BSTree&T,ElemTypee);
voidLeftBalance(BSTree&T);
voidRightBalance(BSTree&T);
intPrint_Mid(BSTreeT);
intVisit(BSTreeT);
intWideTraverse(BSTreeT);
voidDestory(BSTree&T);
intflag=0;
booltaller;
intnumber;//计数变量
voidmain()
{
BSTreeT=NULL;
intchose;
ElemTypee;
printf("\n=======平衡二叉树=======\n");
do{
printf("||功能菜单:
||\n");
printf("||1--创建平衡二叉树||\n");
printf("||2--按要求输出||\n");
printf("||3--插入元素||\n");
printf("||4--销毁二叉树||\n");
printf("||5--退出||\n");
printf("\n请选择:
");
do{
scanf("%d",&chose);
}while(flag==0&&chose!
=1&&chose!
=5&&printf("尚未创建,必须先创建\n请选择:
"));
system("cls");
switch(chose)
{
default:
printf("输入出错\n");
case1:
number=0;
CreatBalanceTree(T);
flag=1;
system("cls");
break;
case2:
printf("共有%d个结点\n",number);
printf("有序输出:
");
Print_Mid(T);
printf("\n\n按层输出:
");
WideTraverse(T);
printf("\n\n\n");
break;
case3:
printf("插入元素:
\n");
printf("请输入关键字(输入0停止):
");
scanf("%d",&e.Key);
flushall();
printf("输入相关信息(0-20字符):
");
scanf("%s",e.info);
InsertAVL(T,e);
break;
case4:
printf("已销毁平衡二叉树\n");
Destory(T);
break;
case5:
printf("确认退出?
1--YES2--NO\n");
if(scanf("%d",&chose),chose==1)
exit
(1);
system("cls");
}
}while
(1);
}
voidCreatBalanceTree(BSTree&T)
{
ElemTypee;
printf("\n\n创建平衡二叉树\n");
printf("请输入关键字(输入0停止):
");
scanf("%d",&e.Key);
while(e.Key)
{
flushall();
printf("输入相关信息(0-20字符):
");
scanf("%s",e.info);
printf("\n");
if(InsertAVL(T,e))
number++;
printf("请输入关键字(输入0停止):
");
scanf("%d",&e.Key);
}
}
intPrint_Mid(BSTreeT)
{
if(T)
{
if(Print_Mid(T->lchild))
if(Visit(T))
if(Print_Mid(T->rchild))
returnOK;
returnERROR;
}
elsereturnOK;
}
intVisit(BSTreeT)
{
printf("%d",T->data.Key);
returnOK;
}
intInitQueue(LinkQueue&Q)
{
Q.front=Q.rear=(QNodeP)malloc(sizeof(QNode));
if(!
Q.front)
returnERROR;
Q.front->next=NULL;
returnOK;
}
intQueueEmpty(LinkQueueQ)
{
if(Q.front==Q.rear)
returnTRUE;
elsereturnFALSE;
}
intEnQueue(LinkQueue&Q,BSTreep)
{
QNodePq=NULL;
q=(QNodeP)malloc(sizeof(QNode));
if(!
q)
returnERROR;
q->e=p;
q->next=NULL;
Q.rear->next=q;
Q.rear=q;
returnOK;
}
intDeQueue(LinkQueue&Q,BSTree&p)
{
QNodePq=NULL;
if(Q.front==Q.rear)
returnERROR;
q=Q.front->next;
p=q->e;
Q.front->next=q->next;
if(!
q->next)
Q.rear=Q.front;
free(q);
returnOK;
}
intWideTraverse(BSTreeT)
{
LinkQueueQ1,Q2;
BSTreep=NULL;
inti=1;
InitQueue(Q1);
InitQueue(Q2);
printf("\n按层输出:
\n");
if(T)
EnQueue(Q1,T);
while((!
QueueEmpty(Q1))||(!
QueueEmpty(Q2)))
{
printf("第%d层:
",i);
if(i%2)
while(!
QueueEmpty(Q1))
{
DeQueue(Q1,p);
Visit(p);
if(p->lchild)
EnQueue(Q2,p->lchild);
if(p->rchild)
EnQueue(Q2,p->rchild);
}
else
while(!
QueueEmpty(Q2))
{
DeQueue(Q2,p);
Visit(p);
if(p->lchild)
EnQueue(Q1,p->lchild);
if(p->rchild)
EnQueue(Q1,p->rchild);
}
printf("\n");
i++;
}
printf("该树共有%d层\n",i-1);
returnOK;
}
intInsertAVL(BSTree&T,ElemTypee)
{
if(!
T)
{
T=(BSTree)malloc(sizeof(BSTNode));
if(!
T)
exit(ERROR);
T->data=e;
T->lchild=T->rchild=NULL;
T->bf=EH;
taller=TRUE;
}
else
{
if(EQ(e.Key,T->data.Key))
{
taller=FALSE;
printf("树中存在此关键字\n");
returnERROR;
}
if(LT(e.Key,T->data.Key))
{
if(!
InsertAVL(T->lchild,e))
returnERROR;
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;
}
}
}
else
{
if(!
InsertAVL(T->rchild,e))
returnERROR;
if(taller)
{
switch(T->bf)
{
caseLH:
T->bf=EH;
taller=FALSE;
break;
caseEH:
T->bf=RH;
taller=TRUE;
break;
caseRH:
RightBalance(T);
taller=FALSE;
break;
}
}
}
}
returnOK;
}
voidLeftBalance(BSTree&T)
{
BSTreelc=NULL,rd=NULL;
lc=T->lchild;
switch(lc->bf)
{
caseLH:
T->bf=lc->bf=EH;
R_Rotate(T);
break;
caseRH:
rd=lc->rchild;
switch(rd->bf)
{
caseLH:
T->bf=RH;
lc->bf=EH;
break;
caseEH:
T->bf=lc->bf=EH;
break;
caseRH:
T->bf=EH;
lc->bf=LH;
break;
}
rd->bf=EH;
L_Rotate(T->lchild);
R_Rotate(T);
}
}
voidRightBalance(BSTree&T)
{
BSTreelc=NULL,rd=NULL;
rd=T->rchild;
switch(rd->bf)
{
caseRH:
T->bf=rd->bf=EH;
L_Rotate(T);
break;
caseLH:
lc=rd->lchild;
switch(lc->bf)
{
caseRH:
T->bf=LH;
rd->bf=EH;
break;
caseEH:
T->bf=rd->bf=EH;
break;
caseLH:
T->bf=EH;
rd->bf=RH;
break;
}
lc->bf=EH;
R_Rotate(T->rchild);
L_Rotate(T);
}
}
voidR_Rotate(BSTree&p)//右旋
{
BSTreelc=NULL;
lc=