二叉排序树的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
1、设计内容 (2)
2、概要设计 (2)
2.1所需模块 (2)
2.2功能模块关系图 (2)
3.算法描述 (3)
3.1模块流程图 (3)
3.2各模块代码 (4)
3.2.1主函数菜单模块 (4)
3.2.2查找模块 (5)
3.2.3插入模块 (5)
3.2.4中序遍历模块 (5)
3.2.5删除模块 (6)
4.运行结果及算法分析 (7)
4.1运行结果 (7)
4.2算法分析 (9)
5.实验心得 (9)
6.程序代码 (10)
7.参考资料 (12)
1、设计内容
用二叉链表为存储结构
1)以回车('\n')为输入结束标志,输入数列L,生成一棵二叉排序树T;
2)对二叉排序树T作中序遍历,输出结果;
3)输入元素x,查找二叉排序树T,若存在含x的结点,则删除该结点,并作中序
遍历(执行操作;否则输出信息“无x”。
2、概要设计
2.1所需模块
根据程序功能,确定所需模块如下:
1)主函数菜单模块;
2)查找模块;
3)插入模块;
4)中序遍历模块;
5)删除模块。
2.2功能模块关系图
图1功能模块图
3.算法描述
3.1模块流程图
图2程序流程图
3.2.1主函数菜单模块
该模块功能主要是给用户提供清晰的可操作界面,易于人机操作。
并能很好的调用其他各模块,使程序更加优化,思路更加清晰,结构更加明了,提高了程序的实用性。
其算法如下:
void main()
{ node T=NULL;
int num;
int ch=0;
node p=NULL;
printf("please input a list of numbers end with zero:");
do{ scanf("%d",&num);
if(!num) printf("you have finished your input!\n");
else insertBST(&T,num);
}while(num);
printf("\n\n---the menu of the opperation---\n"); /*主程序菜单*/
printf("\n 0: exit" );
printf("\n 1: inorder travel the tree");
printf("\n 2: delete");
while(ch==ch)
{ printf("\n choose the opperation to continue:");
scanf("%d",&ch);
switch(ch){
case 0: exit(0); /*0--退出*/
case 1: printf(" The result of the inorder traverse is:\n ");
inorderTraverse(&T); /*1--中序遍历*/
break;
case 2: printf(" Please input the number you want to delete:");
scanf("%d",&num); /*3--删除某个结点*/
if(searchBST(T,num,NULL,&p))
{
T=Delete(T,num);
printf(" You have delete the number successfully!\n ");
inorderTraverse(&T);
}
else printf(" No node %d you want to delete!",num);
break;
default: printf("Your input is wrong!please input again!\n");
break; /*输入无效字符*/
}
}
}
该模块是给用户提供查找功能。
其查找过程是:若二叉排序树为空,则查找失败,结束查找,返回信息NULL;否则,将要查找的值与二叉排序树根结点的值进行比较,若相等,则查找成功,结束查找,返回被查到结点的地址,若不等,则根据要查找的值与根结点值的大小关系决定是到根结点的左子树还是右子树中继续查找(查找过程同上),直到查找成功或者查找失败为止。
其算法如下:searchBST(node t,int key,node f,node *p) /*查找函数*/
{
if(!t) {*p=f;return (0);} /*查找不成功*/
else if(key==t->data) {*p=t;return (1);} /*查找成功*/
else if(key<t->data) searchBST(t->lchild,key,t,p); /*在左子树中继续查找*/ else searchBST(t->rchild,key,t,p); /*在右子树中继续查找*/
}
3.2.3插入模块
在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。
插入过程:若二叉排序树为空,则待插入结点*p作为根结点插入到空树中;当非空时,将待插结点关键字p->item和树根关键字t-> item进行比较,若p->item = t-> item,则无须插入,若p-> item < t-> item,则插入到根的左子树中,若p-> item > t-> item,则插入到根的右子树中。
而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*p作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。
其算法如下:insertBST(node *t,int key)/*插入函数*/
{
node p=NULL,s=NULL;
if(!searchBST(*t,key,NULL,&p)) /*查找不成功*/
{
s=(node)malloc(sizeof(BSTnode));
s->data=key;
s->lchild=s->rchild=NULL;
if(!p) *t=s; /*被插结点*s为新的根结点*/
else if(key<p->data) p->lchild=s;/*被插结点*s为左孩子*/
else p->rchild=s; /*被插结点*s为右孩子*/
return (1);
}
else return (0);/*树中已有关键字相同的结点,不再插入*/
}
3.2.4中序遍历模块
遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。
访问结点所做的操作依赖于具体的应用问题。
二叉树共有三个部分组成,即根结点,根结点的左子树,根结点的右子树。
限定以从左至右方式共有三种遍历方式,即前序遍历,中序遍历,后序遍历。
中序遍历的原则:若被遍
历的二叉树为非空,则依次执行如下操作:
a)以中序遍历方式遍历左子树;
b)访问根结点;
c)以中序遍历方式遍历右子树。
其算法如下:
inorderTraverse(node *t) /*中序遍历函数*/
{
if(*t){
if(inorderTraverse(&(*t)->lchild)) /*中序遍历根的左子树*/
printf("%d ",(*t)->data); /*输出根结点*/
if(inorderTraverse(&(*t)->rchild)); /*中序遍历根的右子树*/
}
return(1) ;
}
3.2.5删除模块
删除模块:删除结点函数,采用边查找边删除的方式。
如果没有查找到,则不对树做任何的修改;如果查找到结点,则分四种情况分别进行讨论:
a)该结点左右子树均为空,可以直接进行删除;
b)该结点仅左子树为空,右子树不为空,用右子树的根结点取代被删除结
点的位置;
c)该结点仅右子树为空,左子树不为空;
d)该结点左右子树均不为空,找到被删除结点右子树中值的最小的结点,
并用该结点取代被删除节点的位置。
其算法如下:
node Delete(node t,int key) /*删除函数*/
{
node p=t,q=NULL,s,f;
while(p!=NULL) /*查找要删除的点*/
{
if(p->data==key) break;
q=p;
if(p->data>key) p=p->lchild;
else p=p->rchild;
}
if(p==NULL) return t; /*查找失败*/
if(p->lchild==NULL) /*p指向当前要删除的结点*/
{
if(q==NULL) t=p->rchild; /*q指向要删结点的父母*/
else if(q->lchild==p) q->lchild=p->rchild; /*p为q的左孩子*/
else q->rchild=p->rchild;/*p为q的右孩子*/
free(p);
}
else{ /*p的左孩子不为空*/
f=p;
s=p->lchild;
while(s->rchild) /*左拐后向右走到底*/
{
f=s;
s=s->rchild;
}
if(f==p) f->lchild=s->lchild; /*重接f的左子树*/
else f->rchild=s->lchild; /*重接f的右子树*/
p->data=s->data;
free (s);
}
return t;
}
4.运行结果及算法分析
4.1运行结果
图3主菜单界面
图4中序排列效果图
图5删除成功效果图
图6删除不成功效果图
4.2算法分析
若二叉树有n个结点深度为h,中序遍历算法的时间复杂度为O(n),空间复杂度为O(h)。
5.实验心得
课程设计是培养学生综合运用所学知识,发现提出分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际能力的具体训练和考察过程。
回顾数据设计这些日子,至今我感慨颇多,的确,学到了很多的东西包括以前在课本上没有学到的知识,还使我懂的了理论和时间结合是很重要
通过这次课程设计,我加深了对数据结构这门课程的理解,更好的掌握了各种二叉数的递归与非递归,树与二叉树的转换。
以及树的中序的递归,非递归算法,层次序的非递归算法的实现,更巩固了自己的C和C++的知识。
在老师的指导、书本上和网络上查找资料下,终于把程序编出来,在此非常感谢老师对我的指导。
6.程序代码
#include<stdio.h>
# include<stdlib.h>
typedef struct Tnode{
int data; /*输入的数据*/
struct Tnode *lchild,*rchild; /*结点的左右指针,分别指向结点的左右孩子*/ }*node,BSTnode;
searchBST(node t,int key,node f,node *p) /*查找函数*/
{
if(!t) {*p=f;return (0);} /*查找不成功*/
else if(key==t->data) {*p=t;return (1);} /*查找成功*/
else if(key<t->data) searchBST(t->lchild,key,t,p); /*在左子树中继续查找*/ else searchBST(t->rchild,key,t,p); /*在右子树中继续查找*/
}
insertBST(node *t,int key)/*插入函数*/
{
node p=NULL,s=NULL;
if(!searchBST(*t,key,NULL,&p)) /*查找不成功*/
{
s=(node)malloc(sizeof(BSTnode));
s->data=key;
s->lchild=s->rchild=NULL;
if(!p) *t=s; /*被插结点*s为新的根结点*/
else if(key<p->data) p->lchild=s;/*被插结点*s为左孩子*/
else p->rchild=s; /*被插结点*s为右孩子*/
return (1);
}
else return (0);/*树中已有关键字相同的结点,不再插入*/
}
inorderTraverse(node *t) /*中序遍历函数*/
{
if(*t){
if(inorderTraverse(&(*t)->lchild)) /*中序遍历根的左子树*/
printf("%d ",(*t)->data); /*输出根结点*/
if(inorderTraverse(&(*t)->rchild)); /*中序遍历根的右子树*/
}
return(1) ;
}
node Delete(node t,int key) /*删除函数*/
{
node p=t,q=NULL,s,f;
while(p!=NULL) /*查找要删除的点*/
{
if(p->data==key) break;
q=p;
if(p->data>key) p=p->lchild;
else p=p->rchild;
}
if(p==NULL) return t; /*查找失败*/
if(p->lchild==NULL) /*p指向当前要删除的结点*/
{
if(q==NULL) t=p->rchild; /*q指向要删结点的父母*/
else if(q->lchild==p) q->lchild=p->rchild; /*p为q的左孩子*/ else q->rchild=p->rchild;/*p为q的右孩子*/
free(p);
}
else{ /*p的左孩子不为空*/
f=p;
s=p->lchild;
while(s->rchild) /*左拐后向右走到底*/
{
f=s;
s=s->rchild;
}
if(f==p) f->lchild=s->lchild; /*重接f的左子树*/
else f->rchild=s->lchild; /*重接f的右子树*/
p->data=s->data;
free (s);
}
return t;
}
void main()
{
node T=NULL;
int num;
int ch=0;
node p=NULL;
printf("please input a list of numbers end with zero:");
do{
scanf("%d",&num);
if(!num) printf("you have finished your input!\n");
else insertBST(&T,num);
}while(num);
printf("\n\n---the menu of the opperation---\n"); /*主程序菜单*/
printf("\n 0: exit" );
printf("\n 1: inorder travel the tree");
printf("\n 2: delete");
while(ch==ch)
{
printf("\n choose the opperation to continue:");
scanf("%d",&ch);
switch(ch){
case 0: exit(0); /*0--退出*/
case 1: printf(" The result of the inorder traverse is:\n ");
inorderTraverse(&T); /*1--中序遍历*/
break;
case 2: printf(" Please input the number you want to delete:");
scanf("%d",&num); /*3--删除某个结点*/
if(searchBST(T,num,NULL,&p))
{
T=Delete(T,num);
printf(" You have delete the number successfully!\n ");
inorderTraverse(&T);
}
else printf(" No node %d you want to delete!",num);
break;
default: printf("Your input is wrong!please input again!\n");
break; /*输入无效字符*/
}
}
}
7.参考资料
《数据结构教程》(第二版)唐发根编著北京航空航天大学出版社。