线索二叉树设计报告.docx
《线索二叉树设计报告.docx》由会员分享,可在线阅读,更多相关《线索二叉树设计报告.docx(17页珍藏版)》请在冰豆网上搜索。
线索二叉树设计报告
河南城建学院
数据结构
课程设计说明书
题目:
线索二叉树的应用
院系:
计算机科学与工程系
专业班级:
0614082
学号:
061408227
学生姓名:
李文龙
指导教师:
张延红
2010年06月25日
1.需求分析-3-
1.1线索功能模块-3-
1.2创建功能模块-3-
1.3删除和添加功能模块-3-
2.概要设计-3-
2.1功能设计-3-
3详细设计-6-
3.1详细代码分析-9-
3.2创建功能模块-11-
3.3调试情况分析-14-
4.总结-15-
4.1编程心得-15-
参考资料-15-
1.需求分析
本程序是用VC++6.0软件,可以实现对二叉树的创建,遍历以及线索等功能的实现,同时实现了界面的操作功能,便于工作人员操作。
1.1线索功能模块
本程序的重点是对二叉树的线索化以及对二叉树删除节点和添加节点后的线索的进行。
1.2创建功能模块
在我们这次编写的这个程序中,可以通过:
广义表构造法,先序和中序构造法,以及中序和后序构造法等三种供你选择,操作者可以通过不同的构建方式来构建所要查询的二叉树。
1.3删除和添加功能模块
在二叉树的基础上进行对二叉树的添加和删除节点。
2.概要设计
2.1功能设计
(1)treenode
二叉树的节点设计,通过这部分模块,指定了二叉树的各个结点位置,为实现二叉树里面的各个功能,实现了相互的连接。
例如:
通过这部分的功能实现,可以直接让双亲指向左右子数,同时,也可以让左右子树和双亲结点相互相连。
实现他们之间的交互功能。
(2)PreOrderTraverse()
二叉树的前序排列运算函数,在这段功能实现上,依据二叉树的性质,实现其相应的功能,并能狗通过输入的前序排列,结合其他情况的排列,生成一个正确的二叉树。
(3)LevelOrderTraverse()
中序排列的运算函数,在这个模块里,我们定义了二叉树的中序排列的定义,以及中序排列的运算方法,在具体的功能实现时,可以结合其他的排序方式生成正确的二叉树。
(4)PostOrderTraverse()
后序二叉树的运算函数,在这个运算函数里,集成了函数的构造运算形式,以及,在对二叉树进行排序的排列的运算方法。
同时,我们还能够结合其他的排列模式,构建合理的二叉树运算。
(5)InOrderTraverse()
遍历二叉树的运算函数,在这个函数模块里,我们主要是用C++语言编写了,二叉树的生成情况,通过相应情况的输入,生成适当的二叉树。
(6)GetData()
获得函数的大小值,并输出。
(7)LeftChild()
左子树节点,在这个函数结构里,我们设定了节点的运算方式,同时通过相应的函数结构实现了,他与双亲及右子树的关系。
(8)RightChild()
右子树函数,同左子树节点功能相同,通过内部结合的函数,联系双亲及右子树。
(9)destroy()
通过相关的函数运算过程,实现删除的运算功能,在我门的本函数中,主要是实现无用节点的删除功能
(10)
BoolInOrderThreading(TreeNode*head);//中序线索
voidInThreading(TreeNode*p,TreeNode*&pre);
voidDisplay1(TreeNode*p);//通过线索进行二叉树的遍历
boolPreOrderThreading(TreeNode*head);//前序线索
voidPreThreading(TreeNode*p,TreeNode*&pre);
voidDisplay2(TreeNode*p);//通过前序线索遍历
boolPostOrderThreading(TreeNode*head);//后序线索
voidPostThreading(TreeNode*p,TreeNode*&pre);
voidDisplay3(TreeNode*p);//通过后序线索遍历
voidDestroy();//消去线索
voidDestory(TreeNode*p);//销毁函数
(11)
boolInsert(Tdata);//插入结点
boolRemove(Tdata);//删除值为data的节点
2.2算法流程图
3详细设计
3.1视图界面设计
(菜单栏显示情况)
(二叉树的界面生成效果)
(遍历显示)
线索化
插入结点
删除节点
3.1详细代码分析
1.线索化模块
template
boolTree:
:
InOrderThreading(TreeNode*head){
if(head==NULL)
return0;
TreeNode*pre=NULL;
if(root==NULL){
head->SetRightChild(head);
head->SetLeftChild(head);
}
else{
pre=head;
InThreading(root,pre);
pre->SetRightChild(head);pre->SetRflag();
head->SetLeftChild(pre);head->SetLflag();
}
return1;
}
template
voidTree:
:
InThreading(TreeNode*p,TreeNode*&pre){
if(p!
=NULL){
InThreading(p->GetLeftChild(),pre);
if(!
p->GetLeftChild()){
p->SetLflag();p->SetLeftChild(pre);}
if(!
pre->GetRightChild()){pre->SetRflag();pre->SetRightChild(p);}
pre=p;
InThreading(p->GetRightChild(),pre);}
}
template
boolTree:
:
PreOrderThreading(TreeNode*head){
if(head==NULL)
return0;
TreeNode*pre=NULL;
if(root==NULL){
head->SetRightChild(head);
head->SetLeftChild(head);
}
else{
pre=head;
PreThreading(root,pre);
pre->SetRightChild(head);pre->SetRflag();
head->SetLeftChild(pre);head->SetLflag();
}
}
template
voidTree:
:
PreThreading(TreeNode*p,TreeNode*&pre){
if(p!
=NULL){
if(pre->GetLflag()==0&&(p->GetData()==pre->GetData()||pre->GetLeftChild()->GetData()==p->GetData())){
return;
}
if(!
p->GetLeftChild()){
p->SetLflag();p->SetLeftChild(pre);}
if(!
pre->GetRightChild()){
pre->SetRflag();pre->SetRightChild(p);}
pre=p;
PreThreading(p->GetLeftChild(),pre);
PreThreading(p->GetRightChild(),pre);
}
}
template
boolTree:
:
PostOrderThreading(TreeNode*head){
if(head==NULL)
return0;
TreeNode*pre=NULL;
if(root==NULL){
head->SetRightChild(head);
head->SetLeftChild(head);
}
else{
pre=head;
PostThreading(root,pre);
if(pre->GetRightChild()==NULL){
pre->SetRightChild(head);pre->SetRflag();}
head->SetLeftChild(pre);head->SetLflag();
}
return1;
}
template
voidTree:
:
PostThreading(TreeNode*p,TreeNode*&pre){
if(p!
=NULL){
PostThreading(p->GetLeftChild(),pre);
PostThreading(p->GetRightChild(),pre);
if(pre->GetLflag()==0&&(p->GetData()==pre->GetData()||pre->GetLeftChild()->GetData()==p->GetData())){
return;
}
if(!
p->GetLeftChild()){
p->SetLflag();p->SetLeftChild(pre);}
if(!
pre->GetRightChild()){
pre->SetRflag();pre->SetRightChild(p);}
pre=p;
}
}
3.2创建功能模块
在这个模块中,我们通过3种方式对二叉树进行创建。
1.
2.前序和中序
3.中序和后序
在这里这写上了广义表方法,其他两种方法是转变为广义表进行二叉树的建立。
template
TreeNode&Tree:
:
operator=(strings){
Destory(root);
root=NULL;
TreeNode*index[1024];
TreeNode*p=NULL;
inttop=-1,sum=0,number=0;
boolmark=1;
for(inti=0;i{
charch=s[i];
switch(ch)
{
case'(':
{
index[++top]=p;
mark=1;
break;
}
case')':
{
top--;
break;
}
case',':
{
mark=0;
break;
}
default:
{
p=newTreeNode(ch);
sum++;
if(root==NULL)
{
root=p;
}
else
{
if(mark)
{
index[top]->SetLeftChild(p);
p->SetParent(index[top]);
}
else
{
index[top]->SetRightChild(p);
p->SetParent(index[top]);
}
}
}
}
}
number=CountNode(root);
if(sum>number)
{
Destory(root);
root=NULL;
}
return*root;
}
3.2删除和添加功能模块
在这个模块中对于已经存在的二叉树进行插入和删除节点。
重点介绍插入节点。
template
boolTree:
:
Insert(Tdata){
TreeNode*p=Find(data);
if(p==NULL)
returnfalse;
else{
cout<"<chari;
i=getch();
cout<";
cin>>data;
if(i=='0')
InsertLeftChild(p,data);
else
InsertRightChild(p,data);
}
returntrue;
}
3.3调试情况分析
(生成二叉树时输入情况)
(在菜单选择时输入错误)
上图为一输入错误情况的处理的显示情况,根据页面显示我们可以看出我们针对运行中可能出现的各种错误进行了相应的错误处理机制,就如上图所言,在我们在生成二叉树的情况时,在我们输入错误的情况时,显示页面会提醒你,你输入有误,在进行功能的选择时,当我们输入的选择情况不满足情况时,我们的设计的对话框会自动提醒你:
您的输入有误,请从新输入。
3.4算法分析
PreOrderTraverse(TreeNode*p)递归先序遍历
InOrderTraverse(TreeNode*p)递归中序遍历
PostOrderTraverse(TreeNode*p)递归后序遍历
对于这三个递归遍历的情况,按惯例来说时间复杂度为O(n),空间复杂度为O(n)
voidPreOrderTraverse(TreeNode*p)非递归先序遍历
voidInOrderTraverse(TreeNode*p)非递归中序遍历
voidPostOrderTraverse(TreeNode*p)非递归后序遍历
对于这三个遍历的情况,时间复杂度为O(n),空间复杂度为O(n)。
这只是针对最坏的情况而言的。
利用栈来进行遍历
LevelTraverse()const;层遍历
对于层遍历来说,时间复杂度为O(n),空间复杂度为O(n)。
这只是针对最坏的情况而言的。
利用队列来进行遍历。
intCountNode(TreeNode*p)查询二叉树的叶子结点个数
对于这个函数,时间复杂度为O(n),空间复杂度为O(log2n)。
intDepth(TreeNode*p)查询二叉树的深度
对于这个函数,时间复杂度为O(n),空间复杂度为O(log2n)。
PrintTree(TreeNode*p)以树的形状输出二叉树
对于这个函数来说,时间复杂度为O(n),空间复杂度为O(n)。
这个函数根据树的深度和层遍历来实现的。
其时间和空间复杂度和树深度,层遍历一致。
Insert(Tdata);//插入结点
Remove(Tdata);//删除值为data的节点
这两个函数都是基于TreeNode*Find(T&data)函数来进行的。
而TreeNode*Find(T&data)函数是走层遍历进行的。
其时间和空间复杂度都为O(n)。
其他线索函数基本走的都是遍历中该其指针的过程,时间复杂度为O(n),空间复杂度为O(n)。
4.总结
4.1编程心得
通过这次实验,我体会到深刻理解数据结构的重要性。
只有真正理解定义数据类型的好处,才能用好这样一种数据结构。
在一开始定义数据结构时,我因为不细心,总会有或多或少的问题出现,如数据域与指针域的定义类型的不同。
在输好了结构体之后,我开始一个个编写本次实验要求实现功能的子函数。
以前在学C++语言时总觉得函数的递归调用是一样很复杂的算法,经常会理解不了而导致编程的错误。
但在这次实验中,二叉树的先序、中序与后序的输出都用了递归算法。
而且用起来并不复杂,这使我更进一步学习理解了函数的递归调用并得到灵活的运用。
当然,本次实验发现自己还有不足的就是对指针认识的不深入,也常常使所设计的程序无法实现需求功能;再者,在利用中序非递归遍历的时候也出现了程序崩溃的错误,这是因为我一开始是打算用链栈的存储结构来实现该子函数的,但在利用栈中的元素是指向二叉链表结点的指针时,我并不能够写出其各遍历的算法语句,因此,经过多番的调试都无法使程序正常运行。
于是,我便放弃用链栈,转而用栈的顺序存储结构来实现。
经过本次实验基本上解决的一些所遇到的问题,我对二叉树的结构等有了较为深入的理解。
我会继续我的兴趣编写程序的,相信在越来越多的尝试之后,自己会不断进步。
参考资料
1.《Visualc++6.0实例精通》谢勇编著----科学出版社
2.《c++代码设计与重用》----人民邮电出版社
3.《VisualC++6.0编程宝典》----电子子工业出版社
4.《数据结构c++语言描述》----应用标准模板类(STL)
5.《C++高级语言程序设计》----清华大学出版社
6.《数据结构(C语言版)》----清华大学出版社
7.《数据结构》----南京大学出版社
8.《数据结构算法与应用(C语言描述)》----机械工业出版社
9.《数据结构与算法》----清华大学出版社
10.《数据结构(c++)版》———电子工业出版社