实验十二叉树的基本操作.docx
《实验十二叉树的基本操作.docx》由会员分享,可在线阅读,更多相关《实验十二叉树的基本操作.docx(19页珍藏版)》请在冰豆网上搜索。
实验十二叉树的基本操作
浙江大学城市学院实验报告
课程名称数据结构基础
实验项目名称实验十二叉树的基本操作
学生姓名专业班级学号
实验成绩指导老师(签名)日期
一.实验目的和要求
1、掌握二叉树的链式存储结构。
2、掌握在二叉链表上的二叉树操作的实现原理与方法。
3、进一步掌握递归算法的设计方法。
二.实验内容
1、建立头文件test10.h,在该文件中定义二叉树的链式存储结构,并编写二叉树的各种基本操作实现函数。
同时建立一个验证操作实现的主函数文件test10.cpp,编译并调试程序,直到正确运行。
注意:
需要用到栈和队列的有关操作。
说明:
二叉树的基本操作可包括:
(1)voidInitBTree(BTreeNode*&BT)//初始化二叉树BT
(2)voidCreateBTree(BTreeNode*&BT,char*a)
//根据字符串a所给出的广义表表示的二叉树建立二叉链表存储结构
(3)intEmptyBTree(BTreeNode*BT)
//检查二叉树BT是否为空,空返回1,否则返回0
(4)intDepthBTree(BTreeNode*BT)//求二叉树BT的深度并返回该值
(5)intFindBTree(BTreeNode*BT,ElemTypex)
//查找二叉树BT中值为x的结点,若查找成功返回1,否则返回0
(6)voidPreOrder(BTreeNode*BT)//先序遍历二叉树BT
(7)voidInOrder(BTreeNode*BT)//中序遍历二叉树BT
(8)voidPostOrder(BTreeNode*BT)//后序遍历二叉树BT
(9)voidLevelOrder(BTreeNode*BT)//按层次遍历二叉树BT
(10)voidPrintBTree(BTreeNode*BT)//输出二叉树BT
(11)voidClearBTree(BTreeNode*&BT)//清除二叉树BT
2、以下内容为第二次实验完成:
(1)请编写函数实现中序遍历的非递归算法。
将此函数输入到前述头文件test10.h中,并在主函数文件test10.cpp中增加测试语句测试这个函数的正确性。
注意需要用到栈的有关操作。
提示:
二叉树中序遍历的非递归算法就是运用栈这种数据结构将递归的中序遍历转换成非递归的中序遍历,采用的是间接转换方式。
中序遍历非递归算法的N-S流程图如下:
注意:
栈中存放的应该是指向结点的指针,即结点的地址,而不是结点的值。
因为,只有根据结点的地址才能在二叉树中查找到该结点。
(2)完成以下算法的设计,并将这些函数输入到前述头文件test10.h中,在主函数文件test10.cpp中增加测试语句测试其正确性。
(a)将二叉树中的所有结点的左右子树进行交换,函数原型如下:
voidChangeBTree(BTreeNode*BT);
(b)统计二叉树中的所有结点数,函数原型如下:
intCountBTree(BTreeNode*BT);
(c)复制一棵二叉树,并返回复制得到的二叉树根结点指针,函数原型如下:
BTreeNode*CopyBTree(BTreeNode*BT);
(d)如果两棵二叉树具有相同的树型,则称它们是相似的。
请编写函数实现判断两棵树是否相似。
函数原型为:
intSimilarTrees(BTreeNode*BT1,BTreeNode*BT2)
(e)摘树叶:
摘除一棵二叉树上的所有叶子结点后返回一棵新的二叉树。
函数原型为:
BTreeNode*RemoveLeaves(BTreeNode*BT1)
3、填写实验报告,实验报告文件取名为report10.doc。
4、上传实验报告文件report10.doc、源程序文件test10.cpp及test10.h到Ftp服务器上(ftp:
//10.61.14.240:
5000)自己的文件夹下。
三.函数的功能说明及算法思路
(包括每个函数的功能说明,及一些重要函数的算法实现思路)
函数功能说明:
(1)voidInitBTree(BTreeNode*&BT)//初始化二叉树BT
(2)voidCreateBTree(BTreeNode*&BT,char*a)
//根据字符串a所给出的广义表表示的二叉树建立二叉链表存储结构
(3)intEmptyBTree(BTreeNode*BT)
//检查二叉树BT是否为空,空返回1,否则返回0
(4)intDepthBTree(BTreeNode*BT)//求二叉树BT的深度并返回该值
(5)intFindBTree(BTreeNode*BT,ElemTypex)
//查找二叉树BT中值为x的结点,若查找成功返回1,否则返回0
(6)voidPreOrder(BTreeNode*BT)//先序遍历二叉树BT
(7)voidInOrder(BTreeNode*BT)//中序遍历二叉树BT
(8)voidPostOrder(BTreeNode*BT)//后序遍历二叉树BT
(9)voidLevelOrder(BTreeNode*BT)//按层次遍历二叉树BT
(10)voidPrintBTree(BTreeNode*BT)//输出二叉树BT
(11)voidClearBTree(BTreeNode*&BT)//清除二叉树BT
(12)voidIn_Order(BTreeNode*BT)//非递归中序遍历二叉树BT
(13)voidChangeBTree(BTreeNode*BT)//将二叉树中的所有结点的左右子树进行交换
(14)intCountBTree(BTreeNode*BT)//统计二叉树中的所有结点数
(15)BTreeNode*CopyBTree(BTreeNode*BT)//复制一棵二叉树,并返回复制得到的二叉树根结点指针
(16)intSimilarTrees(BTreeNode*BT1,BTreeNode*BT2)//如果两棵二叉树具有相同的树型,则称它们是相似的
(17)BTreeNode*RemoveLeaves(BTreeNode*BT1)//摘除一棵二叉树上的所有叶子结点后返回一棵新的二叉树
重要函数思路:
voidIn_Order(BTreeNode*BT):
是通过判断子树的根结点是否为空,若非空就进栈,若空就出栈,并输出元素
BTreeNode*CopyBTree(BTreeNode*BT):
判断根结点是否空,空就返回NULL,非空就申请新结点并将根结点数据复制到新结点,遍历复制左子树并返回,再遍历复制右子树并返回
intSimilarTrees(BTreeNode*BT1,BTreeNode*BT2):
判断同层子树的根结点是否都为空,空就相似,若不同为空就不相似。
递归判断左子树和右子树
BTreeNode*RemoveLeaves(BTreeNode*BT1):
若根结点为空,就返回空结点,若为叶子结点就删除后返回空结点,然后递归左子树和右子树。
四.实验结果与分析
(包括运行结果截图、结果分析等)
五.心得体会
(记录实验感受、上机过程中遇到的困难及解决办法、遗留的问题、意见和建议等。
)
在本实验要注意栈和队列是存放借点的地址,因此在定义时要注意栈和队列的元素类型
【附录----源程序】
Test10.cpp:
#include
#include
#include
typedefcharElemType;
structBTreeNode{
ElemTypedata;
BTreeNode*left;
BTreeNode*right;
};
#include"test10.h"
voidmain()
{
BTreeNode*T1,*T2,*T3;
charch[80],x;//x用于存放查找的数据
InitBTree(T1);//初始化二叉树
cout<<"基本功能测试"<EmptyBTree(T1)?
cout<<"该二叉树为空"<cout<<"该二叉树非空"<printf("请输入广义表:
");
gets(ch);//将广义表保存在ch字符串中
CreateBTree(T1,ch);//建立二叉树
EmptyBTree(T1)?
cout<<"该二叉树为空"<cout<<"该二叉树非空"<cout<<"该树的深度为"<printf("输入要查找的元素1:
");
cin>>x;
FindBTree(T1,x)?
cout<<"该元素在二叉树中"<cout<<"该元素不在二叉树中"<printf("输入要查找的元素2:
");
cin>>x;
FindBTree(T1,x)?
cout<<"该元素在二叉树中"<cout<<"该元素不在二叉树中"<cout<<"先序序列:
";//先序序列
PreOrder(T1);
cout<cout<<"中序序列:
";//中序序列
InOrder(T1);
cout<cout<<"后序序列:
";//后序序列
PostOrder(T1);
cout<cout<<"层序序列:
";//层序序列
LevelOrder(T1);
cout<cout<<"输出二叉树:
";//输出二叉树
PrintBTree(T1);
cout<cout</*————————————————————————————————*/
cout<<"附加功能测试"<cout<<"中序序列(非递归):
";//非递归中序序列
In_Order(T1);
cout<printf("交换前:
");
PrintBTree(T1);
cout<ChangeBTree(T1);//交换左右子树
printf("交换后:
");
PrintBTree(T1);
cout<cout<<"该树共有"<InitBTree(T2);//初始化二叉树
T2=CopyBTree(T1);
cout<<"输出原二叉树:
";//输出二叉树
PrintBTree(T1);
cout<cout<<"输出复制的二叉树:
";//输出二叉树
PrintBTree(T2);
cout<printf("请输入广义表:
");
gets(ch);//将广义表保存在ch字符串中
CreateBTree(T3,ch);//建立二叉树
if(SimilarTrees(T1,T3))//比较T1与T3是否相似
cout<<"原二叉树与刚刚输入的二叉树相似"<else
cout<<"原二叉树与刚刚输入的二叉树不相似"<if(SimilarTrees(T1,T2))//比较T1与T2是否相似
cout<<"原二叉树与复制得到的二叉树相似"<else
cout<<"原二叉树与复制得到的二叉树不相似"<cout<<"输出原二叉树:
";//输出二叉树
PrintBTree(T1);
cout<RemoveLeaves(T1);//摘除叶子结点
cout<<"输出摘除叶子结点的二叉树:
";//输出二叉树
PrintBTree(T1);
cout<}
Test10.h:
/*——————————————顺序栈的操作—————————————————————*/
structStack
{
BTreeNode**stack;//存栈元素
inttop;//栈顶指示器
intMaxSize;//栈的最大长度
};
voidInitStack(Stack&S)//构造一个空栈S
{
S.MaxSize=10;
S.stack=(BTreeNode**)malloc(S.MaxSize*sizeof(BTreeNode*));
if(!
S.stack)
{
cout<<"分配空间失败"<exit
(1);
}
S.top=-1;
}
intEmptyStack(StackS)//若栈S为空栈返回1,否则返回0
{
returnS.top==-1;
}
voidPush(Stack&S,BTreeNode*item)//元素item进栈
{
if(S.top==S.MaxSize-1)
{
S.stack=(BTreeNode**)realloc(S.stack,S.MaxSize*sizeof(BTreeNode*)*2);
S.MaxSize*=2;
}
S.top++;
S.stack[S.top]=item;
}
BTreeNode*Pop(Stack&S)//栈S的栈顶元素出栈并返回
{
BTreeNode*temp;
if(S.top==-1)
{
cout<<"顺序链为空"<exit
(1);
}
S.top--;
temp=S.stack[S.top+1];
returntemp;
}
BTreeNode*Peek(StackS)//取栈S的当前栈顶元素并返回
{
returnS.stack[S.top];
}
/*——————————————循环队列的操作————————————————————*/
structQueue
{
BTreeNode**queue;
intMaxSize;//队列最大存储数
intfront;//头指针,若队列不空,指向队列头元素的前一个位置
intrear;//尾指针,若队列不空,指向队列尾元素
};
voidInitQueue(Queue&Q)//初始化循环队列Q
{
Q.MaxSize=20;
Q.queue=(BTreeNode**)malloc(Q.MaxSize*sizeof(BTreeNode*));
Q.rear=Q.front=0;
}
intEmptyQueue(QueueQ)//判断队列是否为空,空返回1,否则返回0
{
returnQ.rear==Q.front;
}
voidEnQueue(Queue&Q,BTreeNode*item)//进队列
{
if((Q.rear+1)%Q.MaxSize==Q.front)//空间不足,扩大2倍
{
intk=sizeof(BTreeNode*);
Q.queue=(BTreeNode**)realloc(Q.queue,2*Q.MaxSize*k);
if(Q.rear!
=Q.MaxSize-1)
{//移动队列内容,必须要做
for(inti=0;i<=Q.rear;i++)
Q.queue[i+Q.MaxSize]=Q.queue[i];
Q.rear=Q.rear+Q.MaxSize;
}
Q.MaxSize=2*Q.MaxSize;//修改队列最大空间
}
Q.rear=(Q.rear+1)%Q.MaxSize;//元素入队
Q.queue[Q.rear]=item;
}
BTreeNode*OutQueue(Queue&Q)
{
if(Q.rear==Q.front)
{
printf("队列已空无数据元素出队列!
\n");
exit
(1);
}
//先修改front位置,后取走元素
Q.front=(Q.front+1)%Q.MaxSize;
returnQ.queue[Q.front];
}
/*——————————————树的操作—————————————————————*/
voidInitBTree(BTreeNode*&BT)//初始化二叉树BT
{
BT=NULL;
}
voidCreateBTree(BTreeNode*&BT,char*a)
{//根据字符串a所给出的广义表表示的二叉树建立二叉链表存储结构
Stacks;
BTreeNode*p,*t;//p指向新申请的结点,t指向栈顶结点
intk,i=0;//k=1表示将处理左子树,k=2表示处理右子树
BT=NULL;
InitStack(s);
while(a[i])//一个个读入字符进行处理直到读到'\0'为止
{
switch(a[i])
{
case'':
break;
case'(':
Push(s,p);
k=1;
break;
case')':
Pop(s);
break;
case',':
k=2;
break;
default:
//只可能是字符,即结点值
p=(BTreeNode*)malloc(sizeof(BTreeNode));
p->data=a[i];
p->left=p->right=NULL;
if(BT==NULL)
BT=p;
else
{
t=Peek(s);
if(k==1)t->left=p;
elset->right=p;
}
}
i++;
}
}
intEmptyBTree(BTreeNode*BT)
//检查二叉树BT是否为空,空返回1,否则返回0
{
returnBT==NULL;
}
intDepthBTree(BTreeNode*BT)//求二叉树BT的深度并返回该值
{
if(BT==NULL)//空树深度为0
return0;
else
{
intdep1=DepthBTree(BT->left);//先求根结点左子树的深度
intdep2=DepthBTree(BT->right);//再求根结点右子树的深度
if(dep1>dep2)//返回最大值,并加上根结点这一层
returndep1+1;
else
returndep2+1;
}
}
intFindBTree(BTreeNode*BT,ElemTypex)
//查找二叉树BT中值为x的结点,若查找成功返回1,否则返回0
{
if(BT==NULL)
return0;
else
{
if(BT->data==x)return1;
else
{
if(FindBTree(BT->left,x))return1;
if(FindBTree(BT->right,x))return1;
return0;
}
}
}
voidPreOrder(BTreeNode*BT)//先序遍历二叉树BT
{
if(BT)
{
cout<data<<'';//访问根结点
PreOrder(BT->left);//先序遍历左子树
PreOrder(BT->right);//先序遍历右子树
}
}
voidInOrder(BTreeNode*BT)//中序遍历二叉树BT
{
if(BT)
{
InOrder(BT->left);//中序遍历左子树
cout<data<<'';//访问根结点
InOrder(BT->right);//中序遍历右子树
}
}
voidPostOrder(BTreeNode*BT)//后序遍历二叉树BT
{
if(BT)
{
PostOrder(BT->left);//后序遍历左子树
PostOrder(BT->right);//后序遍历右子树
cout<data<<'';//访问根结点
}
}
voidLevelOrder(BTreeNode*BT)//按层次遍历二叉树BT
{//按层次遍历:
利用队列,每次访问队头结点,一旦访问某结点,
//它的左右孩子入队列,该结点出队列
Queueq;//定义一个队列
InitQueue(q);//初始化队列
if(BT)//树不空
{
EnQueue(q,BT);//根结点入队
while(!
EmptyQueue(q))//队列不空
{
BT=OutQueue(q);//出队
cout<data<<'';//访问该结点
if(BT->left!
=NULL)EnQueue(q,BT->left);
if(BT->right!
=NULL)EnQueue(q,BT->right);
}
}
}
voidPrintBTree(BTreeNode*BT)//输出二叉树BT
{
if(BT)//树非空
{
cout<data;//输出根结点
if(BT->left!
=NULL||BT->right!
=NULL)//若非叶子结点,则递归调用输出左右子树
{
cout<<'(';
PrintBTree(BT->l