实验项目五 二叉树基本操作的实现
课程名称:数据结构
实验项目名称:二叉树基本操作的实现
实验目的:
1.掌握树的基本操作—遍历。
实验要求:
1、 分别用递归和非递归的方法实现一棵树的三种遍历。
实验过程:
1、 创建一棵二叉树(二叉树如下图所示);
2、 用递归算法实现对该树的三种遍历;
3、 用非递归算法实现对该树的三种遍历;
4、 输入选项:0或1,0为递归遍历,1为非递归遍历。
5、 根据输入的选项,分别调用递归或非递归算法输出先序、中序、后序遍历序列。
实验报告中给出先序和后序遍历的非递归实现算法代码。
实验结果:
1、输入:ABD##E##CF#G###(创建二叉树)
2、输入:0(递归算法)
3、输出:先序遍历:ABDECFG
中序遍历:DBEAFGC
后序遍历:DEBGFCA
4、输入:1(非递归实现)
5、输出:先序遍历:ABDECFG
中序遍历:DBEAFGC
后序遍历:DEBGFCA
#include<bits/stdc++.h>
using namespace std;
#define TElemType char
typedef int Status;
#define OK 1
#define ERROR 0
char ch;
const int MAXSIZE=110;
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode ,*BiTree;
BiTNode *T;
BiTree q,p;
typedef BiTree SElemType;
typedef struct{//定义顺序栈
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
SqStack S;
Status InitStack(SqStack &S){
S.base=new SElemType[MAXSIZE];
if(!S.base) exit(OVERFLOW);
S.top = S.base;
S.stacksize = MAXSIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)//入栈
{
if(S.top-S.base==S.stacksize) //判断栈满
return ERROR;
*S.top++=e; //元素e压入栈顶,栈顶指针上移一位;
return OK;
}
Status Pop(SqStack &S,SElemType &e){//出栈
if(S.top==S.base) return ERROR;
e=*--S.top;
return OK;
}
SElemType GetTop(SqStack S){//取栈顶元素
if(S.top!=S.base) return *(S.top-1);
}
Status StackEmpty(SqStack &S){
if(S.top-S.base ==0) return OK;
else return ERROR;
}
void CreatBiTree(BiTree &T){//建树
cin>>ch;//读入字符
if(ch=='#')T=NULL;//如果字符为'#',说明已经到了叶结点
else{//递归
T=new BiTNode;
T->data = ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
}
void DgXx(BiTree T){//递归先序
if(T){
cout<<T->data;
DgXx(T->lchild);
DgXx(T->rchild);
}
}
void DgZx(BiTree T){//递归中序
if(T){
DgZx(T->lchild);
cout<<T->data;
DgZx(T->rchild);
}
}
void DgHx(BiTree T){//递归后序
if(T){
DgHx(T->lchild);
DgHx(T->rchild);
cout<<T->data;
}
}
void InRrderTraverse0(BiTree T){//非递归先序
InitStack(S);//初始化栈S
p = T;
while(p||!StackEmpty(S)) {//如果树不为空或者栈不为空
if(p){
Push(S,p) ;//将结点入栈
cout<<p->data;//输出根结点的值
p = p->lchild ;//把左孩子作为根节点
}
else{//如果树空,说明左树已经遍历完成
Pop(S, p) ;//弹出结点
p = p->rchild ;//开始遍历右树
}
}
}
void InRrderTraverse1(BiTree T){//非递归中序遍历
InitStack(S);//初始化栈
p = T;
q = new BiTNode;
while(p||!StackEmpty(S)){
if(p){//p非空
Push(S,p);//根指针进栈
p=p->lchild;//根指针进栈,遍历左子树
}
else{//p为空
Pop(S,q);//退栈
cout<<q->data;//访问根结点
p=q->rchild;//遍历右子树
}
}
}
void InRrderTraverse2(BiTree T){//非递归后序遍历
InitStack(S);
Push(S,T);//把根节点进栈
BiTNode *pre ,*cur;
cur=NULL;//当前结点
pre=NULL;//上一结点
while(!StackEmpty(S)){//栈非空
cur=GetTop(S);//把根节点给当前结点
if((cur->lchild == NULL && cur->rchild == NULL) || (pre != NULL && (pre == cur->lchild ||pre == cur->rchild)))
{//如果左右子树都没有或者左右子树都已经访问过了
cout<<cur->data;//直接输出根结点
Pop(S,cur);//将此时的根节点弹出
pre=cur;//更新pre
}
else{//记得先进右子树后进左子树,这样输出的顺序才对。
if(cur->rchild != NULL){//如果右子树不为空
Push(S,cur->rchild) ;//把右子树进栈
}
if(cur->lchild != NULL){//如果左子树不为空
Push(S,cur->lchild) ;//把左子树进栈
}
}
}
}
int main(){
CreatBiTree(T);
int temp;
printf("请输入遍历二叉树的方法,0:递归遍历,1:递归遍历,其他数字:结束询问\n");
while(scanf("%d",&temp)!=EOF){
if(temp==0){
cout<<"先序遍历:";
cout<<endl;
DgXx(T);
cout<<endl;
cout<<"中序遍历:";
cout<<endl;
DgZx(T);
cout<<endl;
cout<<"后序遍历:";
cout<<endl;
DgHx(T);
cout<<endl;
}
else if(temp==1){
cout<<"先序遍历:";
cout<<endl;
InRrderTraverse0(T);
cout<<endl;
cout<<"中序遍历:";
cout<<endl;
InRrderTraverse1(T);
cout<<endl;
cout<<"后序遍历:";
cout<<endl;
InRrderTraverse2(T);
cout<<endl;
}
else{
break;
}
printf("请输入遍历二叉树的方法,0:递归遍历,1:递归遍历,其他数字:结束询问\n");
}
printf("感谢使用\n");
return 0;
}