二叉排序树及其应用(算法与数据课程设计)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二叉排序树及其应用
一、问题描述
二叉排序树又称二叉查找树,是一种动态的树表,在现实中有着广泛的应用。
选择合适的存储结构,建立二叉排序树,完成插入、删除等基本操作。
并在此基础上,将二叉排序树应用于通讯录的管理。
二、基本要求
1. 选择合适的存储结构实现二叉排序树的建立。
2. 完成二叉排序树的遍历、搜索、插入、删除等操作。
3. 编写应用程序,运用二叉排序树实现通讯录管理。
三、测试数据
1、二叉排序树
建立二叉排序树:“49 38 76 97 13 27 55”
在建立树中搜索:15和13
在建立树中插入:5
在建立树中删除:27
2、通讯录的测试数据
"小雨",1314520
"老赵",3344520
"一辛",1314025
"华仔",3344025
"落落",1234567
"小钰",3142267
"瑞",4384383
"大黄",7654321。
在上表的基础上完成二叉排序树的建立、插入、删除。
四、算法思想
1、二叉排序树的查找,即给定值先与根结点比较,若相等则查找成功,否则根据根据他们之间的大小关系,分别在左子树或右子树查找。
2、二叉排序树的插入,插入的一定是叶子结点,根据查找结果决定插入位置。
3、二叉排序树的删除分三种情况:
1)若*p结点为叶子结点,即P L和P R均为空树。
由于删除叶子结点不破坏整棵树的结构,则只需改其双亲结点的指针即可。
2)若*p结点只有左子树P L或者只有右子树P R,此时只要令P L或P R直接成为其双亲结点*f的左子树即可。
3)若*p的左右子树均不空。
令*p的左子树为*s的左子树,*p的右子树为*s的右子树,如图。
4、在通讯录管理系统的设计中都基于上述二叉排序树的思想。
五、模块化分
1.二叉排序树
1).Search(p,data)
查找二叉排序树中元素。
2).Traverse(p)
中序遍历二叉排序树。
3).Insert(*p,t)
插入结点t。
4).Delete(p,e)
删除值为e的结点
5).main
主函数
2.通讯录
1).Searchnumber(p,data)
查找通讯录中的号码,查找成功输出号码和对应姓名
2).Traverse(p)
查看通讯录中所有号码,按大小顺序排列
3).Insert(*p,s)
添加新号码
4).Delete(p,data)
删除号码
5).Main
用while循环和switch选择结构进行操作
六、数据结构//(ADT)
1.二叉排序树
ADT Binary Sort Tree{
数据对象:int TElemType data;
数据关系:BSTNode *lchild,rchild;
基本操作:
Search(p,data);
初始条件:p、data存在
操作结果:遍历查找成功输出值
Insert(*p,t);
初始条件:p,t存在
操作结果:将t插入到p中
Traverse(p);
初始条件:p存在
操作结果:中序遍历输出二叉排序树
Delete(p,e);
初始条件:p、e存在
操作结果:删除二叉排序树中结点值为e的结点}ADT Binary Sort Tree
2.通讯录
ADT tongxunlu{
数据对象: name,number;
数据关系:BSTNode *lchild,rchild;
基本操作:
Search(p,data.number);
初始条件:p、data存在
操作结果:遍历查找成功输出值
Insert(*p,t);
初始条件:p,t存在
操作结果:将t插入到p中
Traverse(p);
初始条件:p存在
操作结果:中序遍历输出二叉排序树
Delete(p,e);
初始条件:p、e存在
操作结果:删除二叉排序树中结点值为e的结点}ADT tongxunlu
七、源程序
#include <stdlib.h>
#include <stdio.h>
#define NULL 0
#define FALSE 0
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
typedef int TElemType;
typedef struct BSTNode{
TElemType data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
//在二叉排序树中查找
BSTree Search(BSTree T,TElemType data){
BSTNode *p; p=T;
if(p==NULL) return NULL;
else if (p->data==data) return p;
else if (data<p->data) return Search(p->lchild,data); else return Search(p->rchild,data);
}
//在二叉排序树中插入一个新结点
void Insert(BSTree *p,BSTree t){
if (*p==NULL) *p=t;
else if(t->data<(*p)->data) Insert(&((*p)->lchild),t); else if(t->data>(*p)->data) Insert(&((*p)->rchild),t); }
//中序遍历所建二叉排序树
void Traverse(BSTree p){
if(p!=NULL){
Traverse(p->lchild);
printf("%5d",p->data);
Traverse(p->rchild);
}
}
void Delete(BSTree T,TElemType e)
{
BSTNode *p,*f,*s,*q;
f=NULL; p=T;
while(p)
{ if(p->data==e)
break;
f=p;
if(p->data>e)
p=p->lchild;
else
p=p->rchild;
}
//找不到要删除点
if(p==NULL)
if(p==NULL)
printf("no match");
//p左子树空或右子树空
if((p->lchild==NULL)||(p->rchild==NULL)) //p为根
{ if(f==NULL)
if(p->lchild=NULL)
T=p->rchild;
else
T=p->lchild;
//p无左子树
else if(p->lchild==NULL)
if(f->lchild==p)
f->lchild=p->rchild;
else
f->rchild=p->rchild;
//p无右子树
else if(f->lchild==p)
f->lchild=p->lchild;
else
f->rchild=p->lchild;
free(p);
}
//p有左右孩子
else
{ q=p;
s=p->lchild;
while(s->rchild)
{ q=s;
s=s->rchild;
}
if(q==p)
q->lchild=s->lchild;
else
q->rchild=s->lchild;
p->data=s->data;
free(s);
}
}
void MainMenue()
{ fflush( stdin );
printf("\n************** Main Menue ******************\n"); printf("** **\n"); printf("** 1.Traverse **\n"); printf("** 2.search **\n"); printf("** 3.insert **\n"); printf("** 4.delete **\n"); printf("** 0. Exit. **\n"); printf("** **\n"); printf("**********************************************\n"); }
void main()
{
int flag;
TElemType data;
BSTree p,s,q;
char ch;
printf("Please input datas (999999:end):\n");//建立一棵二叉排序树,元素值从键盘输入,直到输入关键字等于9999为止
scanf("%4d",&data);
p=NULL;
while(data!=999999){
s=(BSTree)malloc(sizeof(BSTNode));
s->data=data;
s->lchild=s->rchild=NULL;
Insert(&p,s);
scanf("%d",&data);
}
printf("Create is completed\n");
while (flag)
{
MainMenue();
printf("Please input your choice(0~4): ");
ch=getchar();
switch (ch){
case '1':
Traverse(p); //中序遍历已建立的二叉排序树
printf("\n");
break;
case '2':
printf("Input the data you want to search:");
scanf("%4d",&data);
s=Search(p,data);
if (s!=NULL) printf("success,the value is %4d\n ",s->data);
else printf("no match data!\n");
break;
case '3':
printf("Input the data you want to insert:");
q=(BSTree)malloc(sizeof(BSTNode));
q->data=data;
q->lchild=q->rchild=NULL;
scanf("%d",&data);
q->data=data;
Insert(&p,q);
Traverse(p);
break;
case '4':
printf("\n");
printf("Input the data you want to delete:");
scanf("%d",&data);
Delete(p,data);
Traverse(p);
break;
case '0':exit(0);
}}}
//应用
#include <stdlib.h>
#include <stdio.h>
#define NULL 0
#define FALSE 0
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
typedef struct Info{
char name[20]; //姓名
int number; //电话
}DataType;
typedef struct BSTNode{
DataType data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
//在二叉排序树中查找
BSTree Searchnumber(BSTree T,int number){
BSTNode *p;
p=T;
if (p==NULL) return NULL;
else if (p->data.number==number) return p;
else if (number<p->data.number) return Searchnumber(p->lchild,number); else return Searchnumber(p->rchild,number);
}
//在二叉排序树中插入一个新结点
void Insert(BSTree *p,BSTree t){
if (*p==NULL) *p=t;
else if(t->data.number<(*p)->data.number) Insert(&((*p)->lchild),t);
else if(t->data.number>(*p)->data.number) Insert(&((*p)->rchild),t); }
//中序遍历所建二叉排序树
void Traverse(BSTree p){
if(p!=NULL){
Traverse(p->lchild);
printf("%d,%4s",p->data.number,p->);
printf("\n");
Traverse(p->rchild);
}
}
void Delete(BSTree T,int e)
{
BSTNode *p,*f,*s,*q;
f=NULL; p=T;
while(p)
{ if(p->data.number==e)
break;
f=p;
if(p->data.number>e)
p=p->lchild;
else
p=p->rchild;
}
//找不到要删除点
if(p==NULL)
printf("no match");
//p左子树空或右子树空
if((p->lchild==NULL)||(p->rchild==NULL))
//p为根
{ if(f==NULL)
if(p->lchild=NULL)
T=p->rchild;
else
T=p->lchild;
//p无左子树
else if(p->lchild==NULL)
if(f->lchild==p)
f->lchild=p->rchild;
else
f->rchild=p->rchild;
//p无右子树
else if(f->lchild==p)
f->lchild=p->lchild;
else
f->rchild=p->lchild;
free(p);
}
//p有左右孩子
else{
q=p;
s=p->lchild;
while(s->rchild)
{
q=s;
s=s->rchild;
}
if(q==p)
q->lchild=s->lchild;
else
q->rchild=s->lchild;
p->data.number=s->data.number;
free(s);
}
}
void main()
{int i;
BSTree p,s,q;
DataType a[7]={
{"小雨",1314520},
{"老赵",3344520},
{"一辛",1314025},
{"华仔",3344025},
{"落落",1234567},
{"小钰",3142267},
{"瑞",4384383},
};
p=NULL;
printf("输入号码和姓名:");
printf("\n");
for(i=0;i<7;i++)
{s=(BSTree)malloc(sizeof(BSTNode)); s->data=a[i];
s->lchild=s->rchild=NULL;
Insert(&p,s);}
Traverse(p);
printf("查找:3344520");
printf("\n");
s=Searchnumber(p,3344520);
if (s!=NULL) printf("号码:%d,姓名%2s\n ",s->data.number,s->); else printf("未找到您需要的号码!\n");
printf("\n");
printf("添加号码7654321,大黄");
printf("\n");
q=(BSTree)malloc(sizeof(BSTNode));
strcpy(q->,"大黄");
q->data.number=7654321;
q->lchild=q->rchild=NULL;
Insert(&p,q);
Traverse(p);
printf("\n");
printf("删除号码1234567");
printf("\n");
Delete(p,1234567);
printf("\n");
Traverse(p);
}
八、测试情况
程序的测试结果如下:
1.二叉排序树的测试结果:
输入数据遍历
查找
插入
删除
2.应用通讯录管理九、参考文献
1、严蔚敏,《数据结构 C语言》,清华大学出版社。
2、谭浩强,《c语言程序设计》,清华大学出版社。
小结
通过这次课程设计除了平时老师给予我们树的教导外还让我们对二叉排序树有了更深一层次的了解,对树的结构,树的一些基本操作有了一定的掌握。
二叉排序树与次优二叉树相对,二叉排序树是一种动态树表。
其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的节点时再进行插入。
新插入的结点一定是一个新添加的叶子节点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。
它至多每个结点有两个孩子。
还有左右之分,不能调换。
正因为排序树的这种性质使它在搜索,插入,删除中很强的逻辑性。
他不像普通的树删除结点是没有意义的,因为他的有序使他在不被删除时任要考虑其孩子的排列是他们满足原来的关系。
在查找中由于根结点选取不同他的平均查找长度又有不同,最差为(n+1)/2;最简单是log2n。
在此次设计中,我们遇到了很多问题。
例如在删除节点的时候,不知道如何去连接删除结点后的剩余子树。
经过我们几个的讨论和资料的查阅,了解到如何去完成它,即当被删除结点为叶子结点时直接删除,当不是叶子结点的时候,选取该结点的左子树的最右结点等。
最终将删除结点操作完成了。
整个程序设计中偶尔有一点一点语法的错误,经过仔细检查及程序系统的提示下,问题得以解决。
通过课程设计让本组成员学到了很多,也使我更深刻地意识到,其实每个人都是很坚强的,每个人在平时学习和生活中都有潜在的能力未曾发挥出来,只要有信心、有勇气去面对,就没有解决不了的难题。
通过这段时间的磨合不断加深了我和组员之间的友谊,在过程中寻找快乐,在感悟中得到升华!
此次的设计也让我们了解和学习到很多的东西,二叉排序树在现代社会有着非常广泛的应用。
随着社会信息的丰富化,检索也越来越重要。