二叉树型结构(精选3篇)
二叉树型结构 篇1
数据结构是计算机科学与技术学科的16门核心课程之一[1],它对培养学生的两项专业能力:算法设计与分析的能力、程序设计能力[1]是非常重要的。数据结构也是全国硕士研究生入学统一考试计算机科学与技术学科综合专业的重要部分,其分数占总分的近三分之一。二叉树是数据结构中非常基础的非线性结构,对学好其它非线性结构具有重要的作用。非线性结构的算法与程序设计对于初学者来说是比较抽象的,即使象二叉树这样简单与基础的非线性结构,要掌握它也不是一件容易的事;学好它离不开动脑与动手,上机编程和调试相关算法非常重要,但是学生不易直观检查计算结果,这会影响调试的效率。
检查二叉树结果可以通过输出二叉树的遍历结果来进行,尤其是层序遍历[2];也可以在集成开发环境中通过监视(Watch)追踪左右子树,这不直观也非常繁琐。图形显示二叉树是比较直观和形象的[3],因此在教学中可以采用图形显示[4,5],比如图1;但是它的缺点也很明显,要求学生掌握一定的图形编程,而不少学生在学习数据结构的时候图形编程基础比较弱,因此教与学往往是在命令行的方式下进行输出,即通过printf或cout进行输出(C/C++语言),所以采用图形输出进行数据结构教学有一定的局限性。
叶品菊等开发了在文本方式下显示二叉树的方法[2],该方法用层序进行输出,每一层输出在一行中,但该方法父结点与子结点之间没有任何东西相连(如图2),因而输出的图形不像一颗树,而是结点的有规律的排列,显示的直观性略差。任燕在其编著的教材《数据结构C++语言描述》[6]中,二叉树的示例图是屏幕截图的,从图中可以看出它利用’_’、’/’和’’三种特殊字符把子结点和父结点连接起来,显示效果非常直观与形象,与图形模式下的显示方式基本相同,只是链式存储二叉树需要转换成顺序存储二叉树,“以便使链式存储二叉树能以树状形式显示”[6]。该文给出了一种文本模式的二叉树结构显示方法,该方法利用’_’、’/’和’’三种特殊字符把子结点和父结点连接起来,使用队列对链式存储二叉树进行层序输出,该方法进行较小的改动可以应用于顺序存储二叉树的显示,加入特殊字符’|’经适当修改也可顺利地显示3阶B_树。由于该方法直观形象且是文本模式,因而可以作为数据结构教与学的有效手段之一。
1 显示方法
文本模式下的二叉树显示主要的是计算结点的输出位置,输出位置是由空格的多少来决定的,父结点与子结点之间的连接由三种特殊字符’_’、’/’和’’构成。倒数第一层和倒数第二层之间只需’/’和’’就可连接,左子树由’/’连接,右子树由’’连接。其它层数之间的结点连接由两行构成,第一行连接线由一个或多个’_’与’/’或’’构成,左子树的连接线形如“_____/”,右子树的连接线形如“_____”;第二行的连接只需’/’和’’,左子树是’/’,右子树是’’。其它非连接线位置由空格填充。为了让斜线(/或)指向结点位置,结点不在斜线(/或)的正下方(文献[6]是在正下方),而是偏一格,这样底层结点相邻3个空格,这样的显示效果比文献[6]中的显示效果更为自然和美观。输出的具体编排见图4。
为了计算空格的个数,需要知道二叉树的显示宽度。由于底层结点相隔3个空格,因此二叉树的显示宽度为满二叉树的底层结点数乘4,高度为5的二叉树显示宽度是64个字符长度,高度为6的二叉树显示宽度是128个字符长度。而在文本模式下,由于文本模式每行80个字符(缺省属性)的限制,该文的显示方法只能显示高度不超过5的二叉树。如果要显示高度为6的二叉树,有两种方法,一是修改文本模式每行显示宽度的属性,只要每行可显示超过128个字符即可;二是显示时采用紧凑格式,结点在斜线的正下方[6],这样底层相邻结点之间只有一个空格,高度为6的二叉树显示宽度为64,显示效果见图5,与图3相比美观性略差。文献[2]采用分页的方式来显示高度超过6的二叉树。考虑到该文的方法主要用于教与学,高度为5的满二叉树有31个结点,对于教学来说高度与结点数都足够,因此该文方法不需其它的改动完全满足正常的教学要求。
空格的具体个数依赖于结点所处的层数,计算时分数据域行、第一行连接符和第二行连接符,倒数第一层和倒数第二层之间只有第一行连接符。具体计算公式如下:
数据域:(2n-2个□)a(2n+1个□)(n为树高,□代表空格,a为数据)
第一行连接符:(2n-1个□)(2n-1-3个_)/□(2n-1-3个_)(2n-1+3个□)
第二行连接符:(2n-1-1个□)/(2n-3个□)(2n-1+2个□)
计算第一行连接符时,n=2将导致2n-1-3=-1,因此前面的空格需要减少一个,即2n-1个空格变为2n-1-1个空格。第二行连接符计算时,不会出现这种问题,因为n=2时没有第二行连接符。
2 程序实施
根据以上方法采用C++进行编程,二叉树的类定义如下:
二叉树的输出是从根结点开始,一层一层地输出。每一层分3行输出,第一行输出结点数据,简单起见结点数据类型为字符型;第二行和第三行为连接符,第一行连接符包括三种字符’_’、’/’和’’,第二行只包括’/’和’’两种字符。如果不用字符’_’而用字符’~’也可以,此时第一行连接符包括’/’和’’,第二行包括’~’、’/’和’’三种字符。倒数第一层没有连接符,倒数第二层没有第二行连接符。每一行输出时一个结点一个结点地输出,空结点也需输出,只是结点数据和连接符全部用空格替代。
由于整体输出顺序是层序,因此用结点指针型的队列来处理层序输出;每一层的结点需重复3次进行输出处理,每个结点处理完后需要放回到队列以便重复提取。每一层的3行输出结束后队列需要更新,即下一行的结点进入队列。由于空结点也需处理,队列一直不空,为了充分利用队列,用一个临时结点来表示一层结点的处理结束,否则需要计数处理。加了注释的代码如下:
由于空结点也需要处理,因此代码中有大量的分支语句;为了压缩代码长度,程序编制时大量使用了三目运算符?:。即使这样程序仍有70余行,如果希望进一步压缩代码,三行输出的循环控制压缩到一个循环,此时第一行和第二行的连接符需要存储在两串字符串中,循环结束再输出。这样处理后代码压缩到50余行,压缩量不大且可读性略有下降,不建议这样处理。
3 实例应用
二叉树是数据结构中的基础数据类型,因此应用的地方较多,该文举几个简单的例子。二排序叉树是有利于搜索的数据类型,采用该文方法把搜索的结果用特定字符’*’标识出来如图6。哈夫曼树是一种最优二叉树,带权的初始结点都在叶子上,构造过程中新建的结点都是分支结点;哈夫曼树可以采用顺序存储[6],该文方法略作修改即可应用于顺序存储,用特殊字符’@’标识分支结点显示的哈夫曼树如图7。平衡二叉树是一种优化后的二叉排序树,它的左右子树的高度不超过1,每个结点有一个平衡因子表示左右子树的平衡情况,可以用更为直观的符号表示平衡因子,即’>’代表1、’=’代表0和’<’代表-1,显示时把数据域后面的空格减少一个,用于输出平衡因子的代表符号,显示结果如图8。B_树是一种多路平衡查找树,可用于外部文件的动态查找,B_树的插入与删除算法比较复杂,非常适合学生的编程技能训练,在调试过程中如何快速有效地检查结果比较麻烦,采用该文的方法经适当地修改可以方便地显示3阶B_树。为了显示3阶B_树,增加一个符号’|’指向中间的子树,最重要的修改是显示起始位置的计算,另外用字符’~’替代了字符’_’,此时第一行连接符包括’/’、’|’和’’,第二行包括’~’、’/’、’|’和’’四种字符,这样显示的效果也非常好,如图9。
4 结论
二叉树结构的文本模式显示方法使用了’_’、’/’和’’三种字符来显示二叉树的结构,由于不涉及图形操作,该方法有很强的可移植性,不论TC环境或者VS环境,该文提供的代码都可直接使用。该文的方法也可方便地改为独立的函数,也方便其它的语言实现。该方法方便了树型数据结构程序的调试,不仅可以应用于各种二叉树,也可应用于三叉树,比如3阶B_树。由于直观地显示了二叉树的结构,因而可以提高教与学的效率。同时,算法也使用了队列,对学生巩固已学过的数据结构知识非常有帮助。
参考文献
[1]中国计算机科学与技术学科教程2002研究组.中国计算机科学与技术学科教程2002[M].北京:清华大学出版社,2002.
[2]叶品菊,吴斌,胡远望,等.直观显示二叉树结构的算法[J].江南大学学报:自然科学版,2008,7(1):60-63.
[3]刘福君,李华,王玉森,等.基于二叉树的故障树画树算法研究[J].计算机技术与发展,2006,16(7):117-118.
[4]刘惠敏,董毅.动态模拟二叉树的建立[J].黄冈职业技术学院学报,2004,6(1):75-76.
[5]白雪峰,李沛.二叉排序树的建立及对其中序遍历的动态模拟[J].电脑知识与技术,2005,12(8):84-86.
[6]任燕.数据结构C++语言描述[M].北京:清华大学出版社,2010.
二叉树型结构 篇2
课程名称 数据结构课程设计 题 目平衡二叉树操作 指导教师 设计起止日 2010-5-16 学 院 计算机学院 专 业
软件工程 学生姓名
班级/学号------------成 绩 _________________
一. 需求分析
1、建立平衡二叉树并进行创建、增加、删除、调平等操作。
2、设计一个实现平衡二叉树的程序,可进行创建、增加、删除、调平等操作,实现动态的输入数据,实时的输出该树结构。
3、测试数据:自选数据
二. 概要设计
平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是,则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。具体步骤如下:
⑴ 每当插入一个新结点,从该结点开始向上计算各结点的平衡因子,即计算该结点的祖先结点的平衡因子,若该结点的祖先结点的平衡因子的绝对值均不超过1,则平衡二叉树没有失去平衡,继续插入结点;
⑵ 若插入结点的某祖先结点的平衡因子的绝对值大于1,则找出其中最小不平衡子树的根结点;
⑶ 判断新插入的结点与最小不平衡子树的根结点的关系,确定是哪种类型的调整;
⑷ 如果是LL型或RR型,只需应用扁担原理旋转一次,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;如果是LR型或RL型,则需应用扁担原理旋转两次,第一次最小不平衡子树的根结点先不动,调整插入结点所在子树,第二次再调整最小不平衡子树,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;
⑸ 计算调整后的平衡二叉树中各结点的平衡因子,检验是否因为旋转而破坏其他结点的平衡因子,以及调整后的平衡二叉树中是否存在平衡因子大于1的结点。
三. 详细设计
树的内部变量
typedef struct BTNode { — 2 —
int data;int bf;//平衡因子 struct BTNode *lchild,*rchild;//左、右孩子
}BTNode,*BTree;调平二叉树(左右调平方式大体雷同,之具体写出其中一种调平方式)if(插入元素与当前根元素相等){ printf(“已存在相同关键字的结点n”);} if(插入元素小于当前根元素)){ if(插入新结点不成功)
return 0;if(插入成功)
switch(查看根的平衡因子)
{
case +1:
进行左平衡处理;
{
检查*T的左子树的平衡度,并作相应平衡处理
{
case +1:
令根及其左孩子的平衡因子为0;
做右平衡处理;
{
BTree lc;
lc指向的结点左子树根结点;
rc的右子树挂接为结点的左子树;
lc的右孩子为原结点;
原结点指向新的结点lc;
}
break;
case-1:
rd指向*T的左孩子的右子树根
switch(查看右孩子平衡因子)
{
case +1:
根的平衡因子为-1;
根左孩子的平衡因子为0;
break;
case 0:
令根和根左孩子的平衡因子为0;
break;
case-1:
}
}
}
}
根平衡因子为0;根左孩子平衡因子为1;break;
根右孩子的平衡因子为0;对*T的左子树作左旋平衡处理;对*T作右旋平衡处理;break;令根的平衡因子为+1;break;令根的平衡因子为-1;break;case 0:
case-1:
四.调试分析
在进行对插入新结点并调平时由于利用的是普通的插入方法进行LL、LR、RL、RR型的转换,使得在调试时经常没有更改内部变量的值,导致编译出错。
对于在空树情况下删除结点的考虑,是在后期的调试检验过程中发现的。在没有更改代码前,如果按此操作,程序就会崩溃。原因就是在删除函数中虽然考虑到了空树的情况,但是在输出树的函数中没有加入空树的考虑而只是在创建树函数中加入了if…else…的判断。经过反复的检查,发现可以直接在输出函数中加入判断而不必再其他位置判断,并且调试成功。
五.使用说明和测试结果
测试数据:
创建二叉树
— 4 —
增加二叉树
直接创建平衡二叉树
平衡二叉树加入新节点并调平
删除结点
— 6 —
六.心得体会
了解了建立树的方法;
学会了利用二分法建立树结构。、; 学习到了二叉树的调平方法;
学会了向一个已知树插入或删除结点的方法。七.附录 源代码
#include “stdafx.h” #include
}BTNode,*BTree;
/*需要的函数声明*/ void Right_Balance(BTree &p);void Left_Balance(BTree &p);void Left_Root_Balance(BTree &T);void Right_Root_Balance(BTree &T);bool InsertAVL(BTree &T,int i,bool &taller);void PrintBT(BTree T,int m);void CreatBT(BTree &T);void Left_Root_Balance_det(BTree &p,int &shorter);void Right_Root_Balance_det(BTree &p,int &shorter);void Delete(BTree q,BTree &r,int &shorter);int DeleteAVL(BTree &p,int x,int &shorter);void Adj_balance(BTree &T);bool SetAVL(BTree &T,int i,bool &taller);bool Insert_Balance_AVL(BTree &T,int i,bool &taller);/*主函数*/ void main(){
int input,search,m;bool taller=false;int shorter=0;BTree T;T=(BTree)malloc(sizeof(BTNode));T=NULL;while(1){
printf(“n请选择需要的二叉树操作n”);printf(“1.创建二叉树2.增加新结点3.直接创建平衡二叉树4.在平衡二叉树上增加新结点并调平衡5.scanf(”%d“,&input);getchar();switch(input){ case 1:
CreatBT(T);break;printf(”请输入你要增加的关键字“);scanf(”%d“,&search);getchar();InsertAVL(T,search,taller);m = 0;PrintBT(T,m);break;Adj_balance(T);删除0.退出n”);case 2: case 3: — 8 —
break;
case 4:
printf(“请输入你要增加的关键字”);
scanf(“%d”,&search);
getchar();
SetAVL(T,search,taller);
m = 0;
PrintBT(T,m);
break;
case 5:
printf(“请输入你要删除的关键字”);
scanf(“%d”,&search);
getchar();
DeleteAVL(T,search,shorter);
m=0;
PrintBT(T,m);
break;
case 0:
break;
default:
printf(“输入错误,请重新选择。”);
break;
}
if(input == 0)
break;
printf(“按任意键继续.”);
getchar();} } /*对以*p为根的二叉排序树作右旋处理*/ void Right_Balance(BTree &p){ BTree lc;lc = p->lchild;//lc指向的*p左子树根结点
p->lchild = lc->rchild;//rc的右子树挂接为*p的左子树 lc->rchild = p;p = lc;//p指向新的结点
} /*对以*p为根的二叉排序树作左旋处理*/ void Left_Balance(BTree &p){ BTree rc;rc = p->rchild;//指向的*p右子树根结点
p->rchild = rc->lchild;//rc左子树挂接到*p的右子树
rc->lchild = p;p = rc;//p指向新的结点
— 9 — } /*对以指针T所指结点为根的二叉树作左平衡旋转处理*/ void Left_Root_Balance(BTree &T){
} /*对以指针T所指结点为根的二叉树作右平衡旋转处理*/ void Right_Root_Balance(BTree &T){
BTree rc,ld;rc = T->rchild;//指向*T的左子树根结点
switch(rc->bf)//检查*T的右子树的平衡度,并作相应平衡处理 { case RH: //新结点插入在*T的右孩子的右子树上,要作单左旋处理
T->bf = rc->bf =EH;Left_Balance(T);break;ld = rc->lchild;//ld指向*T的右孩子的左子树根 switch(ld->bf)//修改*T及其右孩子的平衡因子 BTree lc,rd;lc = T->lchild;//指向*T的左子树根结点
switch(lc->bf)//检查*T的左子树的平衡度,并作相应平衡处理 { case LH: //新结点插入在*T的左孩子的左子树上,要作单右旋处理
} T->bf = lc->bf = EH;Right_Balance(T);break;rd = lc->rchild;//rd指向*T的左孩子的右子树根 switch(rd->bf)//修改*T及其左孩子的平衡因子 { case LH:
} rd->bf = EH;Left_Balance(T->lchild);//对*T的左子树作左旋平衡处理 Right_Balance(T);//对*T作右旋平衡处理 T->bf = RH;lc->bf = EH;break;T->bf = lc->bf = EH;break;T->bf = EH;lc->bf = LH;break;case RH: //新结点插入在*T的左孩子的右子树上,要作双旋处理
case EH: case RH: case LH: //新结点插入在*T的右孩子的左子树上,要作双旋处理
— 10 —
}
} { case LH:
} ld->bf = EH;Right_Balance(T->rchild);//对*T的右子树作左旋平衡处理 Left_Balance(T);//对*T作左旋平衡处理 T->bf = EH;rc->bf = RH;break;T->bf = rc->bf =EH;break;T->bf = LH;rc->bf = EH;break;case EH: case RH: /*插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回1,否则返回0*/ bool InsertAVL(BTree &T,int i,bool &taller){
if(!T)//插入新结点,树“长高”,置taller为true {
} else {
if(EQ(i,T->data))//树中已存在和有相同关键字的结点 {
} if(LT(i,T->data))//应继续在*T的左子树中进行搜索 taller = false;printf(“已存在相同关键字的结点n”);return 0;T =(BTree)malloc(sizeof(BTNode));T->data = i;T->lchild = T->rchild =NULL;T->bf = EH;taller = true;{ if(!InsertAVL(T->lchild,i,taller))return 0;} else //应继续在*T的右子树中进行搜索 { if(!InsertAVL(T->rchild,i,taller))return 0;
— 11 — } } return 1;} /*按树状打印输出二叉树的元素,m表示结点所在层次*/ void PrintBT(BTree T,int m){
} /*创建二叉树,以输入-32767为建立的结束*/ void CreatBT(BTree &T){
} int m;int i;bool taller=false;T = NULL;printf(“n请输入关键字(以-32767结束建立二叉树):”);scanf(“%i”,&i);getchar();while(i!=-32767){
} m=0;printf(“您创建的二叉树为:n”);PrintBT(T,m);InsertAVL(T,i,taller);printf(“n请输入关键字(以-32767结束建立二叉树):”);scanf(“%i”,&i);getchar();taller=false;if(T){
} else {
} printf(“这是一棵空树!n”);getchar();int i;if(T->rchild)PrintBT(T->rchild,m+1);printf(“ ”);//打印i 个空格以表示出层次 for(i = 1;i<=m;i++)printf(“%dn”,T->data);//打印T 元素,换行 if(T->lchild)PrintBT(T->lchild,m+1);— 12 — /*删除结点时左平衡旋转处理*/ void Left_Root_Balance_det(BTree &p,int &shorter){
BTree p1,p2;if(p->bf==1)//p结点的左子树高,删除结点后p的bf减,树变矮 {
} else if(p->bf==0)//p结点左、右子树等高,删除结点后p的bf减,树高不变 {
} else //p结点的右子树高 {
p1=p->rchild;//p1指向p的右子树
if(p1->bf==0)//p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变 {
} else if(p1->bf==-1)//p1的右子树高,左旋处理后,树变矮 {
} else //p1的左子树高,进行双旋处理(先右旋后左旋),树变矮 {
p2=p1->lchild;p1->lchild=p2->rchild;p2->rchild=p1;p->rchild=p2->lchild;p2->lchild=p;if(p2->bf==0){
} else if(p2->bf==-1){ p->bf=1;p1->bf=0;p->bf=0;p1->bf=0;Left_Balance(p);p1->bf=p->bf=0;shorter=1;Left_Balance(p);p1->bf=1;p->bf=-1;shorter=0;p->bf=-1;shorter=0;p->bf=0;shorter=1;
}
}
} } else {
} p2->bf=0;p=p2;shorter=1;p->bf=0;p1->bf=-1;/*删除结点时右平衡旋转处理*/ void Right_Root_Balance_det(BTree &p,int &shorter){
BTree p1,p2;if(p->bf==-1){
} else if(p->bf==0){
} else {
p1=p->lchild;if(p1->bf==0){
} else if(p1->bf==1){
} else { p2=p1->rchild;Right_Balance(p);p1->bf=p->bf=0;shorter=1;Right_Balance(p);p1->bf=-1;p->bf=1;shorter=0;p->bf=1;shorter=0;p->bf=0;shorter=1;— 14 —
p1->rchild=p2->lchild;
p2->lchild=p1;
p->lchild=p2->rchild;
p2->rchild=p;
if(p2->bf==0)
{
p->bf=0;
p1->bf=0;
}
else if(p2->bf==1)
{
p->bf=-1;
p1->bf=0;
}
else
{
p->bf=0;
p1->bf=1;
}
p2->bf=0;
p=p2;
shorter=1;
} } } /*删除结点*/ void Delete(BTree q,BTree &r,int &shorter){ if(r->rchild==NULL){
q->data=r->data;
q=r;
r=r->lchild;
free(q);
shorter=1;} else {
Delete(q,r->rchild,shorter);
if(shorter==1)
Right_Root_Balance_det(r,shorter);} } /*二叉树的删除操作*/ int DeleteAVL(BTree &p,int x,int &shorter){
} int k;BTree q;if(p==NULL){
} else if(x
data)//在p的左子树中进行删除 {
} else if(x>p->data)//在p的右子树中进行删除 {
} else {
} q=p;if(p->rchild==NULL)//右子树空则只需重接它的左子树 {
} else if(p->lchild==NULL)//左子树空则只需重接它的右子树 {
} else//左右子树均不空 {
} return 1;Delete(q,q->lchild,shorter);if(shorter==1)Left_Root_Balance_det(p,shorter);p=q;p=p->rchild;free(q);shorter=1;p=p->lchild;free(q);shorter=1;k=DeleteAVL(p->rchild,x,shorter);if(shorter==1)Right_Root_Balance_det(p,shorter);return k;k=DeleteAVL(p->lchild,x,shorter);if(shorter==1)Left_Root_Balance_det(p,shorter);return k;printf(“不存在要删除的关键字!n”);return 0;— 16 — /*二叉树调平操作*/ void Adj_balance(BTree &T){ int m;int i;bool taller=false;T = NULL;printf(“n请输入关键字(以-32767结束建立平衡二叉树):”);scanf(“%d”,&i);getchar();while(i!=-32767){
SetAVL(T,i,taller);
printf(“n请输入关键字(以-32767结束建立平衡二叉树):”);
scanf(“%d”,&i);
getchar();
taller=false;} m=0;printf(“平衡二叉树创建结束.n”);if(T)
PrintBT(T,m);else
printf(“这是一棵空树.n”);} /*调平二叉树具体方法*/ bool SetAVL(BTree &T,int i,bool &taller){ if(!T)//插入新结点,树“长高”,置taller为true {
T =(BTree)malloc(sizeof(BTNode));
T->data = i;
T->lchild = T->rchild =NULL;
T->bf = EH;
taller = true;} else {
if(EQ(i,T->data))//树中已存在和有相同关键字的结点
{
taller = false;
printf(“已存在相同关键字的结点n”);
return 0;
}
if(LT(i,T->data))//应继续在*T的左子树中进行搜索 {
}
}
} if(!SetAVL(T->lchild,i,taller))
{
} case LH: //原本左子树比右子树高,需要作左平衡处理
Left_Root_Balance(T);taller = false;break;T->bf = LH;taller = true;break;T->bf = EH;taller = false;break;return 0;switch(T->bf)//检查*T的平衡度 if(taller)//已插入到*T的左子树中且左子树“长高”
case EH: //原本左子树、右子等高,现因左子树增高而使树增高
case RH: //原本右子树比左子树高,现左、右子树等高
else //应继续在*T的右子树中进行搜索 {
} return 1;if(!SetAVL(T->rchild,i,taller))
{
} case LH: //原本左子树比右子树高,现左、右子树等高
T->bf = EH;taller = false;break;T->bf = RH;taller = true;break;Right_Root_Balance(T);taller = false;break;return 0;switch(T->bf)//检查*T的平衡度 if(taller)//已插入到*T的右子树中且右子树“长高”
case EH: //原本左子树、右子等高,现因右子树增高而使树增高
case RH: //原本右子树比左子树高,需要作右平衡处理
二叉树型结构 篇3
题目名称: 二叉树的应用问题 专业班级: 计算机科学与技术
学生姓名:
学生学号:
指导教师:
目录
一、题目要求..............................................二、需求分析..............................................三、概要设计..............................................四、详细设计..............................................五、调试分析.............................................六、心得体会.............................................一、题目要求
实现二叉树,求解若干二叉树应用问题
实现二叉链表表示的二叉树,包括下列运算:
建立一棵二叉树;
按先序、中序和后序遍历二叉树; 按层次遍历;
求一棵二叉树的高度;
交换一棵二叉树的左右子树;
设计一个菜单驱动程序,测试上述算法
二、需求分析
建立一棵二叉树:
int CreateBiTree(BiTree &T)按先序遍历二叉树:
void PreOrder(BiTree &T)按中序遍历二叉树:
void InOrder(BiTree &T)按后序遍历二叉树:
void PostOrder(BiTree &T)按层次遍历:
void LevelOrder(BiTree &T)求一棵二叉树的高度:
int Depth(BiTree &T)交换一棵二叉树的左右子树:int PreOrderTraverse(BiTree T)菜单驱动程序:
void menu()
三、概要设计
定义二叉树的存储结构,每个结点中设置三个域,即值域、左指针域、右指针域。要建立二叉树T的链式存储结构,即建立二叉链表。根据输入二叉树结点的形式不同,建立的方法也不同,本系统采用先序序列递归建立二叉树。
先序遍历二叉树的操作定义为:若二叉树为空,则空操作;否则:(1)访问根结点;(2)先序遍历左子树;(3)先序遍历右子树。
中序遍历二叉树的操作定义为:若二叉树为空,则空操作;否则:(1)中序遍历左子树;(2)访问根结点;
(3)中序遍历右子树。
后序遍历二叉树的操作定义为:若二叉树为空,则空操作;否则:(1)后序遍历左子树;(2)后序遍历右子树;(3)访问根结点。
层次遍历二叉树的操作选用队列的存储结构。先建立一个长度为1的队列,利用while循环,将根结点放入队首,再将队列长度加一。然后依次遍历左子树和右子树,每遍历一次,2、先序遍历二叉树:
void PreOrder(BiTree &T){ if(!T)
return;cout<
3、中序遍历二叉树:
void InOrder(BiTree &T){ if(!T)return;InOrder(T->left_child);cout<
4、后序遍历二叉树:
void PostOrder(BiTree &T){ if(!T)return;PostOrder(T->left_child);PostOrder(T->right_child);cout<
5、按层次遍历:
void LevelOrder(BiTree &T){ BiTree queue[100];int front,rear;if(T==NULL)return;front=-1;rear=0;queue[rear]=T;while(front!=rear){ front++;cout<
cin>>a;if(a>=0||a<=7){ switch(a){ case 0:
{
cout<<“建立后的二叉树为:n”;
Output(T);
cout< } system(“pause”); break;case 1: cout<<“该树的树深为: ”< system(“pause”); break;case 2: { cout<<“该树以先序遍历输出为:n”; PreOrder(T); cout< } system(“pause”); break;case 3: { cout<<“该树以中序遍历输出为:n”; InOrder(T); cout< } system(“pause”); break;case 4: { cout<<“该树以后序遍历输出为:n”; PostOrder(T); cout< } system(“pause”); break;case 5: { cout<<“该树的层次遍历:n”; LevelOrder(T); cout< (二)详细程序代码:{ if(!T){ cout<<“空树!n”; return;} cout< int Depth(BiTree &T){ int i,j;if(!T)return 0;i=Depth(T->left_child);j=Depth(T->right_child);return(i>j?i:j)+1;} void PreOrder(BiTree &T){ if(!T) return;cout< void InOrder(BiTree &T){ if(!T)return;InOrder(T->left_child);cout< void PostOrder(BiTree &T){ if(!T)return;PostOrder(T->left_child);PostOrder(T->right_child);cout< void LevelOrder(BiTree &T) cout<<“<< 1.二叉树树深 >>”< cout<<“<< 2.二叉树的先序遍历 >>”< cout<<“<< 3.二叉树的中序遍历 >>”< cout<<“<< 4.二叉树的后序遍历 >>”< cout<<“<< 5.二叉树的层次遍历 >>”< cout<<“<< 6.左右孩子交换 >>”< cout<<“<< 7.退出 >>”< cout<<“*******************************************************************”< void main(){ int br,a;BiTree T;br=CreateBiTree(T); while(1){ menu(); cout<<“请输入选择的命令-->”; cin>>a; if(a>=0||a<=7) { switch(a) { case 0: { cout<<“建立后的二叉树为:n”; Output(T); cout< } system(“pause”); break; case 1: cout<<“该树的树深为: ”< system(“pause”); break; case 2: { cout<<“该树以先序遍历输出为:n”; PreOrder(T); cout< } system(“pause”); break; case 3: { cout<<“该树以中序遍历输出为:n”; (一)先序输入二叉树: (二)建立一棵二叉树: 1后序遍历: (四)按层次遍历: 3中序遍历交换后的二叉树: 六、心得体会 【二叉树型结构】推荐阅读: 二叉树结构06-05 数据结构 平衡二叉树的操作演示07-16 树型结构01-13 经济结构与产业结构08-03 砖混结构的结构设计10-01 钢结构住宅结构管理12-29 钢结构住宅结构设计08-29 建筑结构 水工钢筋混凝土结构07-05 数据的逻辑结构与物理结构小结01-09 基于连接结构和主谓结构的歧义分析01-21