数据结构实验报告二叉树.docx
《数据结构实验报告二叉树.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告二叉树.docx(21页珍藏版)》请在冰豆网上搜索。
数据结构实验报告二叉树
数据结构实验报告
实验名称:
实验3——二叉树
学生姓名:
班级:
班内序号:
学号:
日期:
2013年12月2日
1.实验要求
根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。
二叉树的基本功能:
1、二叉树的建立
2、前序遍历二叉树
3、中序遍历二叉树
4、后序遍历二叉树
5、按层序遍历二叉树
6、求二叉树的深度
7、求指定结点到根的路径
8、二叉树的销毁
9、其他:
自定义操作
编写测试main()函数测试线性表的正确性
2.程序分析
2.1存储结构
(1)对于二叉树的存储结构而言,完全二叉树适合于顺序结构存储,避免一维数组的浪费。
(2)另外对于二叉树来说,其存储结构还可以由二叉链表来进行存储。
(3)三叉链表也可以进行二叉树的存储
2.2关键算法分析
1、关键算法:
(1)创建二叉树:
以顺序存储结构作为建立二叉树的输入,根据二叉树的定义,分三步建树a.建立根结点
b.建立左子树
c.建立右子树
(2)前序遍历:
A、如果当前结点非空
a.访问当前结点
b.当前结点入栈;
c.将当前结点的左孩子作为当前结点;
B、如果当前结点为空
a.栈顶结点出栈,
b.将该结点的右孩子作为当前结点;
(3)中序遍历:
A、如果当前结点非空
a.当前结点入栈;
b.将当前结点的左孩子作为当前结点;
B、如果当前结点为空
a.栈顶结点出栈,
b.访问当前结点
c.将该结点的右孩子作为当前结点;
(4)后序遍历:
a.当前结点入栈,访问其左子树
b.利用栈顶结点,访问其右子树
c.当前结点出栈,访问该结点
(5)层序遍历:
A、根结点非空,入队。
B、如果队列不空
a.队头元素出队
b.访问该元素
c.若该结点的左孩子非空,则左孩子入队;
d.若该结点的右孩子非空,则右孩子入队;
(6)求二叉树的深度:
A、如果跟结点为空,返回0;
B、如果跟结点不为空
a.则判断它的左子树和右子树是否为空;
b.如果为空则返回1,不为空则用递归继续做;
(7)求出某个元素的路径:
a.先将二叉树的根结点及其左子树循环下去的左子树全部压入栈中;
b.在判断栈顶元素是否为所寻找的元素
c.如果不是则出栈找寻这个结点的跟结点,判断右子树是否是
所寻找的元素,然后依次用递归进行下去。
(8)析构函数:
a.用后序遍历的方法进行结点的删除。
2、代码详细分析
(1)创建二叉树:
关键算法:
voidBitree:
:
create(Binode*&R,Tdata[],inti)
{
if(data[i-1]!
=0)//i表示的是位置,从一开始到终止为止
{
R=newBinode;//创立根结点
R->data=data[i-1];
R->lch=R->rch=NULL;
create(R->lch,data,2*i);//创建左子树
create(R->rch,data,2*i+1);//创建右子树
}
}
示意图:
(2)前序遍历:
关键算法:
template
voidBitree:
:
preorder(Binode*R)//前序遍历函数
{
if(R!
=NULL)
{
cout<data<(2);
preorder(R->lch);//遍历左子树
preorder(R->rch);//遍历右子树
}
}
示意图:
(3)中序遍历:
关键算法:
template
voidBitree:
:
Inorder(Binode*R)//中序遍历函数
{
if(R!
=NULL)
{
Inorder(R->lch);//遍历左子树
cout<data<(2);//访问结点
Inorder(R->rch);//遍历右子树
}
}
示意图:
(4)后序遍历:
关键算法:
template
voidBitree:
:
Postorder(Binode*R)//后序遍历函数
{
if(R!
=NULL)
{
Postorder(R->lch);//遍历左子树
Postorder(R->rch);//遍历右子树
cout<data<(2);//访问结点
}
}
示意图:
(5)层序遍历:
关键算法:
template
voidBitree:
:
Levelorder(Binode*R)
{
Binode*queue[10000];
intf=0,r=0;//初始化空队列
if(R!
=NULL)
queue[++r]=R;
while(f!
=r)
{
Binode*p=queue[++f];//队头元素打印
cout<data<(2);//出队打印
if(p->lch!
=NULL)
queue[++r]=p->lch;
if(p->rch!
=NULL)
queue[++r]=p->rch;
}
}
示意图:
(6)求出路径:
关键算法:
template
voidBitree:
:
path(Binode*root,charm)//求路径
{
Binode*stack[10000];
Binode*s;
inttag[10000];
inttop=0;
s=root;
do
{
while(s!
=NULL)
{
top++;
stack[top]=s;
tag[top]=0;
s=s->lch;
}
if(top>0)
{
if(tag[top]==1)
{
if(stack[top]->data==m)
{
cout<<"路径:
";
for(inti=1;i<=top;i++)
cout<data<(2);
break;
}
top--;
}
else
{
s=stack[top];
if(top>0)
{
s=s->rch;
tag[top]=1;
}
}
}
}while(s!
=NULL||top!
=0);
}
3、时间复杂度:
2、3其他说明:
关于路径的查找问题其实也可以采用递归的算法,不用像这么复杂。
3、程序运行结果:
(1)测试主函数的流程
(2)源代码:
#include
#include
usingnamespacestd;
templatestructBinode//创立结构数组,结点
{
Tdata;
Binode*lch;
Binode*rch;
};
template
classBitree//建立一个Bitree类
{
private:
voidcreate(Binode*&R,Tdata[],inti);//创建一个二叉树
voidDestroy(Binode*R);//销毁二叉树
public:
Binode*root;
Bitree(Tdata[]);//有参构造函数
Bitree(){};//无参构造函数
voidpreorder(Binode*R);//前序遍历的函数
voidInorder(Binode*R);//中序遍历的函数
voidPostorder(Binode*R);//后序遍历的函数
voidLevelorder(Binode*R);//层序遍历的函数
intDepth(Binode*R,intd);//求二叉树的深度
voidpath(Binode*root,char);//求出二叉树的路径
~Bitree();//析构函数
};
template
voidBitree:
:
create(Binode*&R,Tdata[],inti)
{
if(data[i-1]!
=0)//i表示的是位置,从一开始到终止为止
{
R=newBinode;//创立根结点
R->data=data[i-1];
R->lch=R->rch=NULL;
create(R->lch,data,2*i);//创建左子树
create(R->rch,data,2*i+1);//创建右子树
}
}
template
Bitree:
:
Bitree(Tdata[])//构造函数
{
create(root,data,1);
}
template
voidBitree:
:
preorder(Binode*R)//前序遍历函数
{
if(R!
=NULL)
{
cout<data<(2);
preorder(R->lch);//遍历左子树
preorder(R->rch);//遍历右子树
}
}
template
voidBitree:
:
Inorder(Binode*R)//中序遍历函数
{
if(R!
=NULL)
{
Inorder(R->lch);//遍历左子树
cout<data<(2);//访问结点
Inorder(R->rch);//遍历右子树
}
}
template
voidBitree:
:
Postorder(Binode*R)//后序遍历函数
{
if(R!
=NULL)
{
Postorder(R->lch);//遍历左子树
Postorder(R->rch);//遍历右子树
cout<data<(2);//访问结点
}
}
template
voidBitree:
:
Levelorder(Binode*R)
{
Binode*queue[10000];
intf=0,r=0;//初始化空队列
if(R!
=NULL)
queue[++r]=R;
while(f!
=r)
{
Binode*p=queue[++f];//队头元素打印
cout<data<(2);//出队打印
if(p->lch!
=NULL)
queue[++r]=p->lch;
if(p->rch!
=NULL)
queue[++r]=p->rch;
}
}
//销毁二叉树
template
voidBitree:
:
Destroy(Binode*R)
{
if(R!
=NULL){
Destroy(R->lch);//释放左子树
Destroy(R->rch);//释放右子树
deleteR;//释放根结点
}
}
template
Bitree:
:
~Bitree()//释放二叉树
{
Destroy(root);
}
template
intBitree:
:
Depth(Binode*R,intd)
{
if(R==NULL)returnd;//在这里其实将d当作0,作为形参
if((R->lch==NULL)&&(R->rch==NULL))
returnd+1;
else
{
intm=Depth(R->lch,d+1);//运用递归函数进行深度的递归
intn=Depth(R->rch,d+1);
returnn>m?
n:
m;
}
}
template
voidBitree:
:
path(Binode*root,charm)//求路径
{
Binode*stack[10000];
Binode*s;
inttag[10000];
inttop=0;
s=root;
do
{
while(s!
=NULL)
{
top++;
stack[top]=s;
tag[top]=0;
s=s->lch;
}
if(top>0)
{
if(tag[top]==1)
{
if(stack[top]->data==m)
{
cout<<"路径:
";
for(inti=1;i<=top;i++)
cout<data<(2);
break;
}
top--;
}
else
{
s=stack[top];
if(top>0)
{
s=s->rch;
tag[top]=1;
}
}
}
}while(s!
=NULL||top!
=0);
}
intmain()
{
charbuf[400]={0};
cout<<"请输入一个数"<inti;
cin>>i;
for(inta=0;a
buf[a]=a+65;
}
BitreeChBiTree(buf);
cout<<"前序遍历是"<ChBiTree.preorder(ChBiTree.root);
cout<cout<<"中序遍历是"<ChBiTree.Inorder(ChBiTree.root);
cout<cout<<"后序遍历是"<ChBiTree.Postorder(ChBiTree.root);
cout<cout<<"层序遍历是"<ChBiTree.Levelorder(ChBiTree.root);
cout<cout<<"此二叉树的深度是"<charb;
cin>>b;
ChBiTree.path(ChBiTree.root,buf[b-97]);
cout<return0;
}
(3)程序运行结果:
4、感想和总结:
这次的实验相对于前几次的实验来说要难一些,涉及到了较多的递归函数,然后关于栈的运用更加的灵活。
这次收获最大的在于查找元素的路径,采用了两个栈进行记录,所以程序的语法要求更高,感觉很难。
最终还是将路径给写出来了,感觉很不错。
期间有一些语法错误搞的焦头烂额,后来用了很长的时间才搞定,以后还是要多多变成才行,否则只懂思想不懂怎么写出来也没有什么用,而且学会一门语言对以后的发展还是有很多的好处。