二叉排序树.docx
《二叉排序树.docx》由会员分享,可在线阅读,更多相关《二叉排序树.docx(23页珍藏版)》请在冰点文库上搜索。
二叉排序树
淮阴工学院
数据结构课程设计报告
选题名称:
二叉排序树:
用顺序表结构存储
系(院):
计算机工程系
专业:
网络工程
班级:
网络107
姓名:
周俊学号:
107******5
指导教师:
张亚红张勇军
学年学期:
2008~2009学年第2学期
2009年6月20日
设计任务书
课题
名称
二叉排序树:
用顺序表结构存储
设计
目的
通过一周的课程设计,用顺序表存储结构实现对二叉排序树的的创建,中序遍历,并计算其平均查找长度,查找和某个删除结点等基本操作,达到巩固和运用理论知识、锻炼实践能力、构件合理知识结构和提高程序设计能力的目的。
实验
环境
Windows2000以上操作系统
VisualC++6.0以上编译环境
任务
要求
1、搜集二叉排序树方面的资料;
2、编写代码,实现二叉排序树的创建,中序遍历,计算其平均查找长度,查找和删除某个结点;
3、撰写课程设计报告;
4、参加答辩。
工作进度计划
序号
起止日期
工作内容
1
2009.06.08
搜集二叉排序树方面的资料
2
2009.06.08~2009.06.10
编写代码,上机调试
3
2009.06.11
撰写课程设计报告
4
2009.06.11
答辩
指导教师(签章):
2008年6月25日
课题
名称
二叉排序树:
用顺序表结构存储
设计
目的
通过一周的课程设计,实现背包问题的回溯法求解,进一步加强对数据结构中栈以及C++编程算法中经典回溯法的理解与运用,达到巩固理论知识、锻炼实践能力、构建合理知识的目的。
实验
环境
Windows2000以上操作系统
VisualC++6.0以上编译环境
任务
要求
1.搜集背包问题相关的资料和回溯法的基本原理与算法分析;
2.编写代码,实现背包问题的回溯求解;
3.撰写PPT文件与课程设计报告;
4.参加答辩。
工作进度计划
序号
起止日期
工作内容
1
2009.06.08
理论辅导,搜集资料
2
2009.06.08~2009.06.10
编写代码,上机调试
3
2009.06.11
撰写课程设计报告
4
2009.06.11
答辩
指导教师:
2009年6月10日
摘要:
数据结构是研究与数据之间的关系,我们称这一关系为数据的逻辑结构,简称数据结构。
当数据的逻辑结构确定以后,数据在物理空间中的存储方式,称为数据的存储结构。
相同的逻辑结构可以具有不同的存储结构,因而有不同的算法。
本次课程设计,程序中的数据采用“树形结构”作为其数据结构。
具体采用的是“二叉排序树”,并且使用“一维数组”来作为其存储结构。
一维数组顺序表存储结构是用一组地址连续的存储单元依次自上而下、自左而右存储完全二叉树上的结点元素;本课程设计实现了二叉排序树的创建、中序遍历、计算二叉排序树的平均查找长度和删除二叉排序树中某个结点。
关键词:
二叉排序树;中序遍历;平均查找长度;删除结点
1需求分析
1.1课程设计题目、任务及要求
二叉排序树。
用顺序表(一维数组)作存储结构
(1)以回车('-1')为输入结束标志,输入数列L,生成一棵二叉排序树T;
(2)对二叉排序树T作排序,输出结果;
(3)输入元素x,查找二叉排序树T:
若存在含x的结点,则删除该结点,否则输出信息“无x”;
1.2课程设计思想
建立二叉排序树采用边查找边插入的方式。
查找函数采用递归的方式进行查找。
如果查找成功则不应再插入原树,否则返回当前结点的上一个结点。
然后利用插入函数将该元素插入原树。
对二叉树进行中序遍历采用递归函数的方式。
在根结点不为空的情况下,先访问左子树,再访问根结点,最后访问右子树。
计算二插排序树的平均查找长度时,仍采用类似中序遍历的递归方式,用s记录总查找长度,j记录每个结点的查找长度,s置初值为0,采用累加的方式最终得到总查找长度s。
平均查找长度就等于s/i(i为树中结点的总个数)。
删除结点函数,采用边查找边删除的方式。
如果没有查找到,则不对树做任何的修改;如果查找到结点,则分四种情况分别进行讨论:
1、该结点左右子树均为空;
2、该结点仅左子树为空;
3、该结点仅右子树为空;
4、该结点左右子树均不为空。
1.3软硬件运行环境及开发工具
Windows2000以上操作系统、MicrosoftVisualC++6.0
2概要设计
2.1二叉排序树的定义
二叉排序树是一种动态树表。
二叉排序树的定义:
二叉排序树或者是一棵空树, 或者是一棵具有如下性质的二叉树:
⑴若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
⑵若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
⑶左、右子树本身又各是一棵二叉排序树。
2.2一维数组的存储结构
建立二插排序树,首先用一个一维数组记录下读入的数据,然后再用边查找边插入的方式将数据一一对应放在完全二叉树相应的位置,为空的树结点用“0”补齐。
2.3建立二叉排序树
从空的二叉排序树开始,经过一系列的查找插入操作以后,生成了一棵二叉排序树。
根据二叉排序树的定义,建立一棵二叉排序树的过程是按照待排序序列元素的先后次序,不断动态生成二叉树的结点,逐个插入到二叉树中。
若p为根结点指针,b为当前待插入元素,其过程可以描述为:
(1)若为空树(p=nil),动态生成一个结点,其数据域为当前待插入元素b,左、右指针域为“空”,p指向该结点。
(2)若非空树,比较b与根结点数据data(p)
如果b<data(p),将b插入左子树中;
如果b≥data(p),将b插入右子树中;
左、右子树的插入方式与二叉排序树的插入方式相同。
不断调用上述的插入过程,直到所有待排序序列均排入后,就形成一棵二叉排序树。
由此可见,建立二叉排序树就是多次调用二叉排序树的插入算法。
2.4二叉排序树的生成过程
二叉排序树的生成,采用递归方式的边查找边插入的方式。
如图:
图2.4.1二叉排序树生成流程图
2.5中序遍历二叉树
中序遍历二叉树算法的框架是:
若二叉树为空,则空操作;否则
(1)中序遍历左子树(L);
(2)访问根结点(V);
(3)中序遍历右子树(R)。
中序遍历二叉树也采用递归函数的方式,先访问左子树2i,然后访问根结点i,最后访问右子树2i+1.先向左走到底再层层返回,直至所有的结点都被访问完毕。
2.6二叉排序树的查找
在二叉排序树上进行查找,是一个从根结点开始,沿某一个分支逐层向下进行比较叛等的过程。
它可以是一个递归的过程。
假设我们想要在二叉排序树中查找关键码为x的元素,查找过程从根结点开始。
如果根指针为NULL,则查找不成功;否则用给定值x与根结点的关键码进行比较;如果给定值等于根结点的关键码,则查找成功,返回查找成功的信息,并报告查找到的结点地址。
如果给定值小于根结点的关键码,则继续递归查找根结点的左子树;否则,递归搜索根结点的右子树。
2.7二叉排序树的插入
在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。
为了向二叉排序树中插入一个新元素,必须先检查这个元素是否在树中已经存在。
所以在插入之前,先使用查找算法在树中检查要插入的元素有还是没有。
如果搜索成功,说明树中已经有这个元素,不再插入;如果搜索不成功,说明树中原来没有关键码等于给定值的结点,把新元素加到搜索操作停止的地方。
插入过程:
若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;
当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,
若s->key=t->key,则无须插入,若s->keykey,则插入到根的左子树中,
若s->key<>t->key,则插入到根的右子树中。
而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。
3详细设计和实现
3.1主要功能模块设计
程序主要设计了五个功能:
首先是创建二叉排序树,完成后出现任务菜单,菜单中设计了四个模块:
退出,排序,插入节点和删除结点。
主函数流程如下:
3.2主程序设计
/*以下是用c++实现的二叉排序树的源代码*/
#include
typedefstructTreeNode
{
intkey;
structTreeNode*left;
structTreeNode*right;
}treeNode;
classBiSortTree
{
public:
BiSortTree(void);
voiddesplayTree(void);//显示这个树
voidinsertTree(intkey);//在树中插入一个值
deleteTree(intkey);//在树中删除一个值
treeNode*searchTree(intkey);//在树中查找一个值
~BiSortTree();
private:
treeNode*buildTree(treeNode*head,intnumber);//建立一个树
treeNode*search(treeNode*head,intkey);//查找
treeNode*BiSortTree:
:
searchParent(treeNode*head,treeNode*p);//查找出p的父亲节点的指针
treeNode*BiSortTree:
:
searchMinRight(treeNode*head);//找到右子树中最小的节点
voidshowTree(treeNode*head);//显示
voiddestroyTree(treeNode*head);//删除
treeNode*Head;
};
/**************以下是建立一个二叉排序树****************/
BiSortTree:
:
BiSortTree()
{
cout<<"建立一棵二叉排序树,请输入你要建树的所有数(以-1作为结束标志!
):
"<Head=NULL;
intnumber;
cin>>number;
while(number!
=-1)
{
Head=buildTree(Head,number);
cin>>number;
}
}
treeNode*BiSortTree:
:
buildTree(treeNode*head,intnumber)
{
treeNode*p;
p=newtreeNode;
p->key=number;
p->left=p->right=NULL;
if(head==NULL)
{
returnp;
}
else
{
if(p->keykey)
head->left=buildTree(head->left,number);
else
head->right=buildTree(head->right,number);
returnhead;
}
}
/*****************以下是在一棵二叉排序树插入一个数***********************************/
voidBiSortTree:
:
insertTree(intkey)
{
Head=buildTree(Head,key);
}
/*****************以下是在一个二叉排序树查找一个数是否存在*************************/
treeNode*BiSortTree:
:
searchTree(intkey)
{
returnsearch(Head,key);
}
treeNode*BiSortTree:
:
search(treeNode*head,intkey)
{
if(head==NULL)
returnNULL;
if(head->key==key)
returnhead;
else
{
if(keykey)
returnsearch(head->left,key);
else
returnsearch(head->right,key);
}
}
/************以下是在一个二叉排序树删除一个给定的值*********************************/
BiSortTree:
:
deleteTree(intkey)
{
treeNode*p;
p=NULL;
p=search(Head,key);
if(p==NULL)
{
cout<<"Don'tfindthekey";
}
if(p==Head)
{
Head=NULL;
}
else
{
treeNode*parent;
parent=searchParent(Head,p);
if(p->left==NULL&&p->right==NULL)//叶子节点
{
if(parent->left==p)
{
parent->left=NULL;
}
else
{
parent->right=NULL;
}
}
else//非叶子节点
{
if(p->right==NULL)//该节点没有右孩子
{
if(parent->left==p)
{
parent->left=p->left;
}
else
{
parent->right=p->left;
}
}
else//该点有左右孩子
{
treeNode*rightMinSon,*secondParent;//secondParent为右子树中的最小节点的父亲
rightMinSon=searchMinRight(p->right);
secondParent=searchParent(p->right,rightMinSon);
secondParent->left=rightMinSon->right;
if(p->right==rightMinSon)//右子树中的最小节点的父亲为p
{
p->right=rightMinSon->right;
}
p->key=rightMinSon->key;
}
}
}
}
treeNode*BiSortTree:
:
searchParent(treeNode*head,treeNode*p)
{
if(head->left==p||head->right==p||head==p||head==NULL)
returnhead;
else
{
if(p->keykey)
returnsearchParent(head->left,p);
else
returnsearchParent(head->right,p);
}
}
treeNode*BiSortTree:
:
searchMinRight(treeNode*head)//找到右子树中最小的节点
{
if(head->left==NULL||head==NULL)
{
returnhead;
}
else
{
returnsearchMinRight(head->left);
}
}
/*****************以下是显示一个二叉排序树****************************************/
voidBiSortTree:
:
desplayTree(void)
{
showTree(Head);
cout<}
voidBiSortTree:
:
showTree(treeNode*Head)
{
if(Head!
=NULL)
{
showTree(Head->left);
cout<key<<'';
showTree(Head->right);
}
}
/*****************以下是删除一棵整二叉排序树************************************/
BiSortTree:
:
~BiSortTree()
{
cout<<"已经消除了一棵树"<destroyTree(Head);
}
voidBiSortTree:
:
destroyTree(treeNode*head)
{
if(head!
=NULL)
{
destroyTree(head->left);
destroyTree(head->right);
deletehead;
}
}
/***********主函数**********/
voidprint()
{
cout<"<<<"1.显示树"<<<"2.插入一个节点"<<<"3.寻找一个节点"<<<"4.删除一个节点"<}
voidmain()
{
BiSortTreetree;
intnumber;
intchoiceNumber;
charflag;
while
(1)
{
print();
cout<<"请选择你要进行的操作(1~4)"<cin>>choiceNumber;
switch(choiceNumber)
{
case1:
tree.desplayTree();break;
case2:
cout<<"请插入一个数:
"<cin>>number;
tree.insertTree(number);
tree.desplayTree();
break;
case3:
cout<<"请插入你要找数:
"<cin>>number;
if(tree.searchTree(number)==NULL)
{
cout<<"没有发现"<}
else
{
cout<<"发现"<}
break;
case4:
cout<<"请输入你要删除的数:
"<cin>>number;
tree.deleteTree(number);
tree.desplayTree();
break;
default:
break;
}
cout<<"你是否要继续(Y/N)?
"<cin>>flag;
if(flag=='N'||flag=='n')
break;
}
}
4调试与操作说明
4.1程序调试
图4.1.1调试界面
在程序调试过程当中,编译时并没有报错,但是运行时总是出错,在查阅资料和老师的帮助下,发现程序未对数组初始化。
添加数组初始化代码:
T.data=(int*)malloc(N*sizeof(int));
4.2程序操作说明
输入一组数列,以结-1结束:
图4.2.1运行界面一
显示数:
图4.2.2运行界面二
插入一个数:
图4.2.3运行界面三
删除一个结点:
图4.2.4运行界面四
总结
这次课程设计使我对做系统的认识深刻了许多。
我真正体会到了在整个过程给我带来的无奈与快乐。
综合起来,主要体现在以下几个方面:
首先,我对数据结构掌握的还不错,在设计二叉树时候没有费多少功夫。
但是由于在宿主语言上的不足给我很大的打击。
眉毛胡子一把抓,没有实质性的进展。
我终于认识到问题的根源所在。
然后我只好再次认真细致地对开发过程进行了规划和分析,才逐渐弄清了整个系统的流程。
其次,在编程语言的熟悉程度也让我对整个开发过程受到了一定的阻碍。
编程知识的不足使我沮丧过,但是认识到我的不足,我于是就向精通c++的同学进行探讨,终于解决了一些难题。
总的来说,这次课程设计给了我很大启发,不管什么问题,只要抓住根源,从不同方面去攻破它,终究会成功,生活也如此。
致谢
历经一个星期的课程设计结束了,我也松了一口气。
应该说这个星期是个收获不少的星期,我在这个星期中学到了很多的东西,特别是团结的精神。
一开始对这个课程设计不是很有兴趣,因为有很多的东西我无法弄懂,就连里面最基本的东西我都要费很大的精力才能略知皮毛,就别谈做完整个课题了,有时候真的想放弃,一走了之,但是想想,这也是锻炼自己的好机会,就硬着头皮做下去,但是越是到最后就越做不下去,不懂得东西逐渐增多,这使我对本来最基本的框架都模糊了,找不到头绪,但是在这个时候,我的同学帮助了我,他不但更我讲了如何设计基本的框架,还教会了我怎么利用书籍库查询,我受益匪浅,与此同时我也上网查询了很多的资料,发现基本上框架是相似的,就是实现的方法不同,也就是说,不同是因为她们用了不同德语言,我用的是access结合vb做出来的,vb的功能很强大,其实在试验过程中,我最要感谢的就是我们的实验老师,他给了我很大的帮助以及动力,当在我想放弃的时候,总是他给我我莫大的帮助,让我信心百倍,让我重拾信心,最终我调试出了结果,我很高心很开心。
这对我以后的学习计算机的知识有了很大的鼓舞。
我相信只要坚持不懈,总会有结果的。
参考文献
1.魏雪萍.新编Word2003入门与提高.北京:
人民邮电出版社,2005
2.王宏生.数据结构.北京:
国防出版社,2006.1
3.潭浩强.程序设计.北京:
清华大学出版社,2000
4.严蔚敏,吴伟民.数据结构.北京:
清华大学出版,2001
5.殷人昆.数据结构.北京:
清华大学出版社,2004
6.王晓东.数据结构与算法设计.电子工业出版社2002
7.陈慧南.数据结构与算法C++语言描述.高等教育出版社2005
8.窦延平等.数据结构与算法C++.上海交通大学出版社2005
指导教师评语
学号
1071304135
姓名
周俊
班级
网络107
选题
名称
二叉排序树:
用顺序表结构存储
序号
评价内容
权重(%)
得分
1
考勤记录、学习态度、工作作风与表现。
5
2
自学情况:
上网检索机时数、文献阅读情况(笔记)。
10
3
论文选题是否先进,是否具有前沿性或前瞻性。
5
4
成果验收:
是否完成设计任务;能否运行、可操作性如何等。
20
5
报告的格式规范程度、是否图文并茂、语言规范及流畅程度;主题是否鲜明、重心是否突出、论述是否充分、结论是否正确;是否提出了自己的独到见解。
30
6
文献引用是否合理、充分、真实。
5
7
答辩情况:
自我陈述、回答问题的正