二叉排序树与平衡而叉树.docx
《二叉排序树与平衡而叉树.docx》由会员分享,可在线阅读,更多相关《二叉排序树与平衡而叉树.docx(29页珍藏版)》请在冰豆网上搜索。
二叉排序树与平衡而叉树
攀枝花学院
学生课程设计(论文)
题目:
二叉排序树与平衡二叉树的实现
学生姓名:
杨莎学号:
201210803040
所在院(系):
数学与计算机学院
专业:
网络工程
班级:
网络工程1班
指导教师:
职称:
攀枝花学院本科学生课程设计任务书
题 目
1、课程设计的目的
1)使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法。
2)使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力。
3)使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设计的基本
2、课程设计的内容和要求(包括原始数据、技术要求、工作要求等)
(1)
(1)以回车('\n')为输入结束标志,输入数列L,生成一棵二叉排序树T;
(2)对二叉排序树T作中序遍历,输出结果;
(3)计算二叉排序树T查找成功的平均查找长度,输出结果;
(4)输入元素x,查找二叉排序树T,若存在含x的结点,则删该结点,并作中序遍历(执行操作2);否则输出信息“无x”;
(5)用数列L,生成平衡的二叉排序树BT:
当插入新元素之后,发现当前的二叉排序树BT不是平衡的二叉排序树,则立即将它转换成新的平衡的二叉排序树BT;
(6)计算平衡的二叉排序树BT的平均查找长度,输出结果。
3、主要参考文献
[1]刘大有等,《数据结构》(C语言版),高等教育出版社
[2]严蔚敏等,《数据结构》(C语言版),清华大学出版社
[3]WilliamFord,WilliamTopp,《DataStructurewithC++》清华大学出版社
[4]苏仕华等,数据结构课程设计,机械工业出版社
4、课程设计工作进度计划
第1天完成方案设计与程序框图
第2、3天编写程序代码
第4天程序调试分析和结果
第5天课程设计报告和总结
指导教师(签字)
日期
年月日
教研室意见:
年月日
学生(签字):
接受任务时间:
年月日
注:
任务书由指导教师填写。
课程设计(论文)指导教师成绩评定表
题目名称
评分项目
分值
得分
评价内涵
工作
表现
20%
01
学习态度
6
遵守各项纪律,工作刻苦努力,具有良好的科学工作态度。
02
科学实践、调研
7
通过实验、试验、查阅文献、深入生产实践等渠道获取与课程设计有关的材料。
03
课题工作量
7
按期圆满完成规定的任务,工作量饱满。
能力
水平
35%
04
综合运用知识的能力
10
能运用所学知识和技能去发现与解决实际问题,能正确处理实验数据,能对课题进行理论分析,得出有价值的结论。
05
应用文献的能力
5
能独立查阅相关文献和从事其他调研;能提出并较好地论述课题的实施方案;有收集、加工各种信息及获取新知识的能力。
06
设计(实验)能力,方案的设计能力
5
能正确设计实验方案,独立进行装置安装、调试、操作等实验工作,数据正确、可靠;研究思路清晰、完整。
07
计算及计算机应用能力
5
具有较强的数据运算与处理能力;能运用计算机进行资料搜集、加工、处理和辅助设计等。
08
对计算或实验结果的分析能力(综合分析能力、技术经济分析能力)
10
具有较强的数据收集、分析、处理、综合的能力。
成果
质量
45%
09
插图(或图纸)质量、篇幅、设计(论文)规范化程度
5
符合本专业相关规范或规定要求;规范化符合本文件第五条要求。
10
设计说明书(论文)质量
30
综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。
11
创新
10
对前人工作有改进或突破,或有独特见解。
成绩
指导教师评语
指导教师签名:
年 月 日
摘要
二叉排序树:
(1)若左子树不空,则左子树上所有节点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有节点均大于它的根结点的值;(3)它的左右子树分别为二叉排序树。
二叉平衡树:
若不是空树,则
(1)左右子树都是平衡二叉树;
(2)左右子树的深度之差的绝对值不超过1。
本次实验是利用二叉排序树和平衡二叉树达到以下目的:
(1)以回车('\n')为输入结束标志,输入数列L,生成一棵二叉排序树T;
(2)对二叉排序树T作中序遍历,输出结果;(3)计算二叉排序树T查找成功的平均查找长度,输出结果;(4)输入元素x,查找二叉排序树T,若存在含x的结点,则删该结点,并作中序遍历(执行操作2);否则输出信息“无x”;(5)用数列L,生成平衡的二叉排序树BT:
当插入新元素之后,发现当前的二叉排序树BT不是平衡的二叉排序树,则立即将它转换成新的平衡的二叉排序树BT;(6)计算平衡的二叉排序树BT的平均查找长度,输出结果。
关键词数列L,结点,二叉排序树,平衡二叉树
目录
摘要1
1概述3
1.1前言3
1.1.1描述3
1.2目的3
2系统设计3
2.1基本概念介绍3
2.1.1树的概念:
4
2.1.2平衡二叉树的概念4
2.2插入结点6
2.3删除结点6
2.4中序遍历7
3编码7
3.1创建二叉树7
3.2遍历8
3.3递归算法9
3.4队列遍历9
3.5主函数10
4测试12
4.1创建平衡二叉树测试12
4.2插入结点测试13
4.3删除结点测试14
4.4中序遍历二叉树15
4.5先序遍历二叉树15
结论16
参考文献18
附录A:
程序代码19
1概述
1.1前言
1.1.1描述
平衡二叉树(BalancedBinaryTree)又被称为AVL树(有别于AVL算法),且具有以下性质:
它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
构造与调整方法平衡二叉树的常用算法有红黑树、AVL、Treap、伸展树等。
最小二叉平衡树的节点的公式如下F(n)=F(n-1)+F(n-2)+1这个类似于一个递归的数列,可以参考Fibonacci数列1是根节点F(n-1)是左子树的节点数量F(n-2)是右子数的节点数量。
1.2目的
通过本程序的设计编写所要求达到的目的是:
1.充分理解和掌握二叉树、平衡二叉树的相关概念和知识。
2.掌握平衡二叉树的生成、结点删除、插入等操作过程。
3.并实现从键盘上输入一系列数据(整型),建立一棵平衡二叉树。
4.任意插入或删除一个结点后仍然要求构成平衡二叉树。
5.按先序和中序遍历输出这棵平衡二叉树。
2系统设计
2.1基本概念介绍
2.1.1树的概念:
树(Tree)是n(n>=0)个结点的有限集。
在任意一棵非空树中:
1)有且仅有一个特定的称为根的结点;当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2......Tm,其中每一个集合又是一棵树,并且称为根的子树(SubTree)。
图1是有8个结点的树,其中A是根,其余结点分成2个子集:
T1={B,D},T2={C,E,F,G,H};T1和T2都是根A的子树,且本身也是一棵树。
图1
2.1.2平衡二叉树的概念
形态匀称的二叉树称为平衡二叉树(Balancedbinarytree):
若T是一棵非空二叉树,其左、右子树分别为TL和TR,令hl和hr分别为左、右子树的深度。
当且仅当
①TL、TR都是平衡二叉树;
②|hl-hr|≤1;
时,则T是平衡二叉树。
(a)平衡二叉树(b)非平衡二叉树
图1-2平衡二叉树与非平衡二叉树
图2平衡二叉树的生成过程
2.2插入结点
在平衡二叉排序树BBST上插入一个新数据元素e的递规算法可以描述如下:
(1)若BBST为空树,则插入一个数据元素为e的新结点作为BBST的根结点,树的深度增加1;
(2)若e的关键字和BBST的根结点的关键字相等,则不进行插入;
(3)若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加1时,分别就下列情况处理之:
1.BBST的根结点的平衡因子为-1(右子树深度大于左子树深度):
则将根结点的平衡因子更改为0,BBST的深度不变;
2.BBST的根结点的平衡因子为0(左,右子树深度相等):
则将根结点的平衡因子更改为1,BBST的深度增加1;
3.BBST的根结点的平衡因子为1(左子树深度大于右子树深度):
若BBST的左子树根结点的平衡因子为1,则需要进行单向右旋平衡处理,并且在右旋处理之后将根结点和右子树根结点的平衡因子更改为0,树的深度不变;
若BBST的左子树根结点的平衡因子为-1,这需进行先向左后向右的双向旋转平衡处理,并且在旋转处理之后,修改根结点和其左、右子树根结点的平衡因子,树的深度不变;
若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e相同关键字的结点,则将e插入在BBST的右子树上,并且当插入之后的右子树深度增加1时,分别就不同情况处理。
2.3删除结点
删除结点过程与插入结点的操作类似,基本过程是:
平衡二叉树--找到要删除的结点--删除一个结点--变成二叉树--旋转--变回平衡二叉树。
具体过程将详细设计中的代码。
2.4中序遍历
右遍历的定义可知,中序遍历二叉树的递规算法可以定义为:
若二叉树为空,则空操作;否则
1)中序遍历左子树
2)访问根结点
3)中序遍历右子树
如中序遍历图2-4的二叉树,结点的访问顺序为:
a→b→c→d→e→f→g
图2-4
3编码
3.1创建二叉树
#include"stdio.h"
#include"string.h"
#include
#defineMax20//结点的最大个数
typedefstructnode{
chardata;
structnode*lchild,*rchild;
}BinTNode;//自定义二叉树的结点类型
typedefBinTNode*BinTree;//定义二叉树的指针
intNodeNum,leaf;//NodeNum为结点数,leaf为叶子数
//==========基于先序遍历算法创建二叉树==============
//=====要求输入先序序列,其中加入虚结点"#"以示空指针的位置==========
BinTreeCreatBinTree(void)
{
BinTreeT;
charch;
if((ch=getchar())=='#')
return(NULL);//读入#,返回空指针
else{
T=(BinTNode*)malloc(sizeof(BinTNode));//生成结点
T->data=ch;
T->lchild=CreatBinTree();//构造左子树
T->rchild=CreatBinTree();//构造右子树
return(T);
}
}
3.2遍历
voidPreorder(BinTreeT)
{
if(T){
printf("%c",T->data);//访问结点
Preorder(T->lchild);//先序遍历左子树
Preorder(T->rchild);//先序遍历右子树
}
}
voidInorder(BinTreeT)
{
if(T){
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);
}
}
voidPostorder(BinTreeT)
{
if(T){
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c",T->data);
}
}
3.3递归算法
inthl,hr,max;TreeDepth(BinTreeT)
{
if(T){
hl=TreeDepth(T->lchild);//求左深度
hr=TreeDepth(T->rchild);//求右深度
max=hl>hr?
hl:
hr;//取左右深度的最大值
NodeNum=NodeNum+1;//求结点数
if(hl==0&&hr==0)leaf=leaf+1;//若左右深度为0,即为叶子。
return(max+1);
}
elsereturn(0);
}
3.4队列遍历
voidLevelorder(BinTreeT)
{
intfront=0,rear=1;
BinTNode*cq[Max],*p;//定义结点的指针数组cq
cq[1]=T;//根入队
while(front!
=rear)
{
front=(front+1)%NodeNum;
p=cq[front];//出队
printf("%c",p->data);//出队,输出结点的值
if(p->lchild!
=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->lchild;//左子树入队
}
if(p->rchild!
=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->rchild;//右子树入队
}
}
}
3.5主函数
voidmain()
{
BinTreeroot;
inti,depth;
printf("\n");
printf("CreatBin_Tree;Inputpreorder:
");//输入完全二叉树的先序序列,
root=CreatBinTree();//创建二叉树,返回根结点
do{//从菜单中选择遍历方式,输入序号。
printf("\t**********select************\n");
printf("\t1:
PreorderTraversal\n");
printf("\t2:
IorderTraversal\n");
printf("\t3:
Postordertraversal\n");
printf("\t4:
PostTreeDepth,Nodenumber,Leafnumber\n");
printf("\t5:
LevelDepth\n");//按层次遍历之前,先选择4,求出该树的结点数。
printf("\t0:
Exit\n");
printf("\t*******************************\n");
scanf("%d",&i);//输入菜单序号(0-5)
switch(i){
case1:
printf("PrintBin_treePreorder:
");
Preorder(root);//先序遍历
break;
case2:
printf("PrintBin_TreeInorder:
");
Inorder(root);//中序遍历
break;
case3:
printf("PrintBin_TreePostorder:
");
Postorder(root);//后序遍历
break;
case4:
depth=TreeDepth(root);//求树的深度及叶子数
printf("BinTreeDepth=%dBinTreeNodenumber=%d",depth,NodeNum);
printf("BinTreeLeafnumber=%d",leaf);
break;
case5:
printf("LevePrintBin_Tree:
");
Levelorder(root);//按层次遍历
break;
default:
exit
(1);
}
printf("\n");
}while(i!
=0);
}
4测试
4.1创建平衡二叉树测试
第一步:
选择1,如图4-1
第二步:
输入序列(10,24,30,88,53)创建一刻二叉平衡树,以0为结尾,如下图
图4-1
第三步:
为查看创建结果,我们选择5,先序输出二叉树,如图
图4-2
4.2插入结点测试
第一步:
选择2,插入一个新结点,其值为7,插入后选择5,
图4.3
第二步:
先序输出该树:
图4.4
4.3删除结点测试
第一步:
选择3删除一个结点,这里删除结点7
第二步:
先序输出该树:
4.4中序遍历二叉树
第一步:
输入4,中序遍历二叉树:
4.5先序遍历二叉树
第一步:
输入5,先序遍历二叉树:
结论
通过平衡二叉树的生成程序的设计,我们很好的理解了平衡二叉树的生成和各项操作的相关知识,同时还较好的掌握了动态查找相关概念。
平衡二叉树的生成是数据结构中一个重要的存储结构。
本程序比较复杂,需要使用结构体并使用了指针。
必须将程序分解为多个子程序以降低编写难度。
适当使用全局常量可以控制有效控制内存溢出。
参考文献
[1]刘大有等,《数据结构》(C语言版),高等教育出版社
[2]严蔚敏等,《数据结构》(C语言版),清华大学出版社
[3]WilliamFord,WilliamTopp,《DataStructurewithC++》清华大学出版社
[4]苏仕华等,数据结构课程设计,机械工业出版社
附录A:
程序代码
#include"stdio.h"
#include"string.h"
#include
#defineMax20
typedefstructnode{
chardata;
structnode*lchild,*rchild;
}BinTNode;
typedefBinTNode*BinTree;
intNodeNum,leaf;
BinTreeCreatBinTree(void)
{
BinTreeT;
charch;
if((ch=getchar())=='#')
return(NULL);
else{
T=(BinTNode*)malloc(sizeof(BinTNode));
T->data=ch;
T->lchild=CreatBinTree();
T->rchild=CreatBinTree();
return(T);
}
}
voidPreorder(BinTreeT)
{
if(T){
printf("%c",T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
voidInorder(BinTreeT)
{
if(T){
Inorder(T->lchild);
printf("%c",T->data);
Inorder(T->rchild);
}
}
voidPostorder(BinTreeT)
{
if(T){
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c",T->data);
}
}
inthl,hr,max;TreeDepth(BinTreeT)
{
if(T){
hl=TreeDepth(T->lchild);
hr=TreeDepth(T->rchild);
max=hl>hr?
hl:
hr;
NodeNum=NodeNum+1;
if(hl==0&&hr==0)leaf=leaf+1;
return(max+1);
}
elsereturn(0);
}
voidLevelorder(BinTreeT)
{
intfront=0,rear=1;
BinTNode*cq[Max],*p;
cq[1]=T;
while(front!
=rear)
{
front=(front+1)%NodeNum;
p=cq[front];
printf("%c",p->data);
if(p->lchild!
=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->lchild;
}
if(p->rchild!
=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->rchild;
}
}
}
voidmain()
{
BinTreeroot;
inti,depth;
printf("\n");
printf("CreatBin_Tree;Inputpreorder:
");
root=CreatBinTree();
do{
printf("\t**********select************\n");
printf("\t1:
PreorderTraversal\n");
printf("\t2:
IorderTraversal\n");
printf("\t3:
Postordertraversal\n");
printf("\t4:
PostTreeDepth,Nodenumber,Leafnumber\n");
printf("\t5:
LevelDepth\n");
printf("\t0:
Exit\n");
printf("\t*******************************\n");
scanf("%d",&i);
case1:
printf("PrintBin_treePreorder:
");
Preorder(root);
break;
case2:
printf("PrintBin_TreeInorder:
");
Inorder(root);
break;
case3:
printf("PrintBin_TreePostorder:
");
Postorder(root);
break;
case4:
depth=TreeDepth(ro