构建一棵二叉排序树的C程序的设计方案Word文件下载.docx
- 文档编号:20463199
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:32
- 大小:263.90KB
构建一棵二叉排序树的C程序的设计方案Word文件下载.docx
《构建一棵二叉排序树的C程序的设计方案Word文件下载.docx》由会员分享,可在线阅读,更多相关《构建一棵二叉排序树的C程序的设计方案Word文件下载.docx(32页珍藏版)》请在冰豆网上搜索。
4.具体设计
首先定义二叉排序树的数据类型如下:
typedefstructnode
{
intkey;
//关键字项
structnode*lchild,*rchild;
//左右孩子指针
}Bstnode;
然后按一定顺序来编写算法程序:
4.1递归查找算法
具体思想如下:
(1)若二叉树为空,则查找失败。
(2)否则,将根结点的关键值与待查关键字进行比较,若相等,则查找成功;
若根结点关键值大于待查值,则进入左子树重复此步骤,否则,进入右子树重复此步骤;
若在查找过程的中遇到二叉排序树的叶子结点时,还没有找到待查结点,则查找不成功。
if(t==NULL)
returnNULL;
else{
if(t->
data==x)
returnt;
if(x<
t->
data)
return(Bsearch(t->
lchild,x));
else
return(Bsearch(t->
rchild,x));
}
二叉排序树归查找算法流程图
4.2非递归查找算法
查找过程是从根结点开始逐层向下进行的。
并定义一个标记量记录是否找到结点。
Bstnode*searchBST(Bstnode*t,intx)
Bstnode*p;
intflag=0;
p=t;
//定义*p结点用于逐层查找,丛根结点开始查找
while(p!
=NULL)//二叉排序树不为空
{
if(p->
key==x)//查找成功
{
printf("
该结点值存在!
"
);
flag=1;
break;
}
//查找不成功,到下一层继续查找
if(x<
p->
key)
p=p->
lchild;
//查找左子树
rchild;
//查找右子树
if(flag==0)
printf("
找不到值为%d的结点!
x);
p=NULL;
returnp;
}
Y
YN
二叉排序树非递归查找算法流程图
4.3插入算法
从根结点开始,根据比较规则,逐一与待插入结点的值比较,查找到插入结点在二叉排序树中的未来位置,然后插入该结点。
将一个关键字的值为x的结点s插入到二叉排序树中,方法如下:
(1)若二叉排序树为空,则关键字值为x的结点s成为二叉排序树的根。
(2)若二叉排序树非空,则将x与二叉排序树的根进行比较,如果x的值等于根结点关键字的值,则停止插入;
如果x的值小于根结点关键字的值,则将x插入左子树;
如果x的值大于根结点关键字的值,则将x插入右子树。
Bstnode*InsertBST(Bstnode*t,intx)//插入关键值为x的元素
Bstnode*s,*p,*f;
//*s为待插结点,*p为逐层查找结点,*f为待插结点的父结点
p=t;
=NULL)
f=p;
//查找过程中,f指向*p的父结点
if(x==p->
key)//若二叉树中已有关键值为x的元素,无需插入
s=(Bstnode*)malloc(sizeof(Bstnode));
s->
key=x;
lchild=NULL;
s->
rchild=NULL;
if(t==NULL)//原树为空,新结点作为二叉排序树的根
returns;
f->
f->
lchild=s;
//新结点作为*f左孩子
else
rchild=s;
//新结点作为*f右孩子
returnt;
插入算法流程图
4.4二叉排序树的生成算法
建立二叉排序树,就是反复在二叉排序树中插入新的结点。
插入的原则是如果待插入结点的值小于根结点的值,则插入到左子树中,否则插入到右子树中。
大致方法是:
首先建一棵空二叉排序树,然后逐个读入元素,每读入一个元素,就建一个新结点,并调用上述二叉排序树的插入算法,将新结点插入到当前已生成的二叉排序树中,最终生成一棵二叉排序树。
Bstnode*CreateBST()
Bstnode*t;
t=NULL;
//设置二叉排序树的初态为空
scanf("
%d"
&
key);
while(key!
=endflag)
t=InsertBST(t,key);
scanf("
4.5中序遍历算法
voidInorder(Bstnode*t)
if(t!
Inorder(t->
lchild);
Printf(“%4d\n”,t->
rchild);
先遍历左孩子,再遍历父结点,最后遍历右孩子。
由于是对一个二叉排序树进行中序遍历,遍历结果则是一个有序序列
4.6删除算法
1.待删除结点*p无左孩子,也无右孩子,则*p的父结点对应的孩子指针置空;
2.待删除结点*p有左孩子,无右孩子,则*p的左孩子替代自己;
3.待删除结点*p无左孩子,有右孩子,则*p的右孩子替代自己;
4.待删除结点*p有左孩子,也有右孩子,本课程(数据结构与算法)给出了两种法:
方法一:
首先找到待删结点*p的前驱结点*s,然后将*p的左子树改为*p父结点的左子树,而*p的右子树改为*s的右子树:
f->
lchild=p->
rchild=p->
free(p);
方法二:
首先找到待删结点*p的前驱结点*s,然后用结点*s的值替代结点*p的值,再将结点*s删除,结点*s的原左子树改为*s的双亲结点*q的右子树:
p->
data=s->
data;
q->
rchild=s->
free(s);
我采用的是第二种算法。
删除算法流程图
4.7主函数
voidmain()
inti,j,k;
Bstnode*tree,*p;
system("
cls"
★☆★☆★请先建立一棵二叉排序树★☆★☆★\n\n"
输入其结点信息(输入一组正整数,当输入0时结束):
\n"
tree=CreateBST();
中序遍历的二叉排序树:
Inorder(tree);
二叉排序树的根为:
%d\n"
tree->
for(;
;
)
switch(i=mainmenu())
case0:
exit(0);
case1:
switch(j=searchmenu())
case1:
search_Bitree(tree);
break;
case2:
printf("
\n请输入要查找的结点的值:
scanf("
k);
p=searchBST(tree,k);
printf("
break;
//default:
输入有误!
break;
case2:
tree=insert_Bitree(tree);
case3:
tree=delete_Bitree(tree);
case4:
中序遍历后的序列为:
print_Bitree(tree);
Inorder(tree);
//default:
4.8注意事项:
其中,某些函数顺序一定不能颠倒。
例如建立二叉排序树函数一定是在插入算法之后。
编写完基本操作算法后,为最后主函数的输出模块作准备,又分别写了递归查找模块、插入模块、删除模块、显示模块。
5.运行环境
MicrosoftVisualC++6.0;
MicrosoftWord2010
6.上机调试
6.1语法错误及修改
在编写程序时,很容易出现分号漏写和括号不匹配的现象,以及缺少返回值的问题。
例如:
在编写非递归查找算法时:
Bstnode*searchBST(Bstnode*t,intx)
if(p->
key==x)
printf("
找到了!
returnp;
找不到值为%d的结点"
returnNULL;
结果编译时出现了警告warning:
'
searchBST'
:
notallcontrolpathsreturnavalue
然后我做了改动,改后程序如下:
{printf("
{printf("
将NULL值赋给指针p,再在程序结尾返回p,此时,编译结果就正确了!
6.2程序输出调整:
在递归查找算法(Bsearch)中针对查找结果如何,没有用明确的输出函数表示出来。
于是我添加了一个递归查找模块如下:
search_Bitree(Bstnode*t)
ints;
s);
if(s!
=0)
{p=Bsearch(t,s);
if(p==NULL)
该结点值不存在!
else
s);
这样主函数便可直接调用该函数来实现查找过程。
6.3时间和空间性能分析:
由于二叉排序树的中序遍历序列为一个递增的有序序列,这样可以将二叉排序树看作是一个有序表。
其查找过程:
若查找成功,则是从根结点出发走了一条从根到某个结点的路径;
若查找不成功,则是从根结点出发走了一条从根到某个叶子结点的路径。
和关键字比较次数不超过二叉排序树的深度。
二叉排序树的平均查找长度与其形态有关。
最坏情况是具有n个结点的单支树,其平均查找长度与顺序查找相同,为(n+1)/2;
即平均查找长度的数量级为O(n)。
在最好情况下,二叉排序树形态均匀,它的平均查找长度与二分查找相似,大约是log2n,其平均查找长度的数量级为O(log2n)。
1、经验与体会:
由于该设计问题是对数据结构与算法课程中二叉树章节的灵活应用,所以课本给了我很大的帮助,结合所学知识以及对二叉排序树的理解,来编写该程序。
7.测试结果及分析
1、
建立如图(a)的二叉排序树,输入的数据依次为:
4524531228900(0为输入结束符),屏幕(图
(1))上显示的是横置的二叉树
图(a)图(b)
图
(1)
2、选择方框中给定的项目(输入0~4中任意数)。
若输入错误会有提示,可以重新输入。
图
(2)
3、输入1,则出现查找菜单。
选择查找方法。
图(3)
4、在查找菜单选1,则进行递归查找。
图(4)
5、同理,若选择2,则进行非递归查找。
查找的值存在与否都会有显示。
图(5)
6、选2,则进行插入操作。
插入关键值为13的结点后,显示如图(6),即插入13后的横置的二叉排序树(图(c)——图(d))。
图(c)图(d)
图(6)
1、选3,进行删除操作。
删除关键值为24的结点后,显示如图(7),即删除24后的横置的二叉排序树(图(e)——图(f))
、
图(e)图(f)
图(7)
2、选4则显示详细信息。
如图(8)所示,按中序遍历(从小到大)依次输出,并显示每个结点的孩子情况,最后打印出横置的二叉排序树。
图(8)
3、选0则退出程序。
图(9)
8.用户使用说明
用户可以根据本程序运行过程中出现的提示性语句来进行操作。
要注意括号中的提示,若没有按照提示输入的话,程序可能将无法继续进行下去。
例如开始输入数据时直到输入0时才算结束输入,从而进行下一步操作。
在遇到选项时,选择错误会给你重新选择的机会。
提示:
进行一系列插入删除等操作后,可以选择显示项来显示最后的二叉排序树状态(二叉排序树显示的是中序遍历后的序列)。
9.参考文献
(1)王昆仑.红.数据结构与算法.:
中国铁道,2007.6
(2)王昆仑.红.数据结构与算法试验指导,2009
(3)谭浩强.c程序设计.:
清华大学,2005.7
(4)严蔚敏.数据结构:
c语言版.:
清华大学,2002
(5)耿.等.数据结构:
用c语言描述.:
高等教育,2004
设计过程中质疑(或答辩)记载:
1.二叉树运行过程中用了什么排序?
答:
运用了中序遍历排序。
2.中序遍历排序是怎样的?
答:
3.在设计过程中遇到过那些困难?
答:
在编程序的过程的程序一直不能正确运行,最后发现函数的调用出现了问题。
最后通过修改解决。
指导教师评语:
签名:
2016年7月5日
附录
#include"
stdio.h"
malloc.h"
stdlib.h"
#defineendflag0//定义endflag为关键字输入结束的标志
//二叉排序树的结点结构
//二叉排序树的查找算法之一(递归)
Bstnode*Bsearch(Bstnode*t,intx)
if(t==NULL)//二叉排序树为空,查找失败
key==x)//查找成功,返回当前结点
//进入左子树递归查找
//进入右子树递归查找
//递归查找函数(显示查找结果)
voidsearch_Bitree(Bstnode*t)
//定义待查结点的关键值
//定义待查的结点
p=Bsearch(t,s);
//递归查找
if(p!
=NULL)
//二叉排序树的查找算法之二(非递归)
Bstnode*searchBST(Bstnode*t,intx)
//二叉排序树的结点插入算法
//中序遍历(递归法)
=NULL)//若二叉树不空
//遍历左孩子
%4d"
t->
//遍历右孩子
}
//二叉排序树的结点删除算法
Bstnode*DeleteBST(Bstnode*t,intk)//删除关键值为k的元素
Bstnode*p,*f,*s,*q;
//*p为待删结点,*f为*p父结点,*s为*p的中序前驱结点,*q为*s的父结点
f=NULL;
//从根结点开始查找,并将*f置空
//查找关键值为k的待删结点*p
key==k)break;
//若找到,则退出循环
//未找到时将*f替代*p,*p则下移进入左右子树继续查找
key>
k)
if(p==NULL)returnt;
//若找不到,则返回原二叉排序树的根指针
//查找成功后,对*p的删除过程
lchild==NULL||p->
rchild==NULL)//若*p无左子树或无右子树
if(f==NULL)//若*p是原二叉排序树的根
if(p->
lchild==NULL)t=p->
//无左孩子,右孩子做根
elset=p->
}//无右孩子,左孩子做根
elseif(p->
lchild==NULL)//若*p无左子树
if(f->
lchild==p)f->
lchild=p->
//p是*f的左孩子
elsef->
//p是*f的右孩子
else//若*p无右子树
free(p);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 构建 二叉排序树 程序 设计方案
![提示](https://static.bdocx.com/images/bang_tan.gif)