/* 数据结构分析与学习专栏
* Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
* All rights reserved.
* 作 者: 高祥
* 完成日期: 2015 年 4 月 12 日
* 版 本 号:018
*任务描述:针对二叉树遍历,实现7种方法
* 1:层次遍历二叉树 ;
* 2:先序遍历二叉树递归实现 ;
* 3:中序遍历二叉树递归实现;
* 4:后序遍历二叉树递归实现 ;
* 5:先序遍历二叉树非递归实现;
* 6:中序遍历二叉树非递归实现 ;
* 7:后序遍历二叉树非递归实现 ;
*主要函数:
* 1.void CreateByPreOrder(BinaryTree &T);//给定完整的先序遍历建树
* 2.void LevelTraverse(BinaryTree T);//层次遍历
* 3.void PreOrderTraverse1(BinaryTree T);//先序遍历递归实现
* 4.void InOrderTraverse1(BinaryTree T);//中序遍历递归实现
* 5.void PostOrderTraverse1(BinaryTree T);//后序遍历递归实现
* 6.void PreOrderTraverse2(BinaryTree T);//先序遍历非递归实现
* 7.void InOrderTraverse2(BinaryTree T);//中序遍历非递归实现
* 8.void PostOrderTraverse2(BinaryTree T);//后序遍历非递归实现
*运行示例
请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):
ABC##DE#G##F###
层序遍历为:
A B C D E F G
递归版本的先、中、后序遍历:
先序遍历为:
A B C D E G F
中序遍历为:
C B E G D F A
后序遍历为:
C G E F D B A
非递归版本的先、中、后序遍历:
先序遍历为:
A B C D E G F
中序遍历为:
C B E G D F A
后序遍历为:
C G E F D B A
是否继续程序?请输入Y/N(分别代表是、否):Y
请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):
ABD##EF#G###CH#J##I#K##
层序遍历为:
A B C D E H I F J K G
递归版本的先、中、后序遍历:
先序遍历为:
A B D E F G C H J I K
中序遍历为:
D B F G E A H J C I K
后序遍历为:
D G F E B J H K I C A
非递归版本的先、中、后序遍历:
先序遍历为:
A B D E F G C H J I K
中序遍历为:
D B F G E A H J C I K
后序遍历为:
D G F E B J H K I C A
是否继续程序?请输入Y/N(分别代表是、否):N
*/
#include<iostream>
#include<queue>
#include<stack>
#include<cstdlib>
using namespace std;
typedef char ElemType;
typedef struct BTNode//二叉树结点类型
{
ElemType data;
struct BTNode *leftchild;
struct BTNode *rightchild;
} BTNode,*BinaryTree;
void CreateByPreOrder(BinaryTree &T);//给定完整的先序遍历建树
void LevelTraverse(BinaryTree T);//层次遍历
void PreOrderTraverse1(BinaryTree T);//先序遍历递归实现
void InOrderTraverse1(BinaryTree T);//中序遍历递归实现
void PostOrderTraverse1(BinaryTree T);//后序遍历递归实现
void PreOrderTraverse2(BinaryTree T);//先序遍历非递归实现
void InOrderTraverse2(BinaryTree T);//中序遍历非递归实现
void PostOrderTraverse2(BinaryTree T);//后序遍历非递归实现
int main()
{
char operate='y';
while(operate=='y'||operate=='Y')
{
BinaryTree T;
cout<<"请输入某棵二叉树的先序遍历(若某结点的左/右子结点不存在,用‘#’表示):\n";
CreateByPreOrder(T);
cout<<"层序遍历为:\n";
LevelTraverse(T);
cout<<"\n递归版本的先、中、后序遍历:\n";
cout<<"\n先序遍历为:\n";
PreOrderTraverse1(T);
cout<<"\n中序遍历为:\n";
InOrderTraverse1(T);
cout<<"\n后序遍历为:\n";
PostOrderTraverse1(T);
cout<<"\n\n非递归版本的先、中、后序遍历:\n";
cout<<"\n先序遍历为:\n";
PreOrderTraverse2(T);
cout<<"\n中序遍历为:\n";
InOrderTraverse2(T);
cout<<"\n后序遍历为:\n";
PostOrderTraverse2(T);
cout<<"\n\n是否继续程序?请输入Y/N(分别代表是、否):";
cin>>operate;
}
return 0;
}
void CreateByPreOrder(BinaryTree &T)//给定完整的先序遍历建树
{
ElemType ch;
cin>>ch;
if(ch=='#')
{
T=NULL;//空结点
}
else
{
T=(BinaryTree)malloc(sizeof(BTNode));//建立根结点
T->data=ch;
CreateByPreOrder(T->leftchild);//建立当前根结点的左子结点
CreateByPreOrder(T->rightchild);//建立当前根结点的右子结点
}
}
void LevelTraverse(BinaryTree T)//层次遍历
{
if(T)
{
//利用数据结构队列实现:首先将根结点入队。在队列不为空的前提下:
//取出队列首元素T,输出其值并删除队列首元素,若T的左子结点存在,将其入队;
//若T的右子结点存在,将其入队。重复该过程直至队列为空。
queue<BinaryTree> Q;
Q.push(T);//根结点入队
while(!Q.empty())//在队列不为空的前提下
{
BinaryTree now=Q.front();//取出队列首元素T
cout<<now->data<<" ";//输出其值
Q.pop();//删除队列首元素
if(now->leftchild)//若T的左子结点存在,将其入队
{
Q.push(now->leftchild);
}
if(now->rightchild)//若T的右子结点存在,将其入队
{
Q.push(now->rightchild);
}
}
cout<<endl;
}
}
void PreOrderTraverse1(BinaryTree T)//先序遍历递归实现
{
if(T)
{
cout<<T->data<<" ";//访问根结点
PreOrderTraverse1(T->leftchild);//访问左子结点
PreOrderTraverse1(T->rightchild);//访问右子结点
}
}
void InOrderTraverse1(BinaryTree T)//中序遍历递归实现
{
if(T)
{
InOrderTraverse1(T->leftchild);//访问左子结点
cout<<T->data<<" ";//访问根结点
InOrderTraverse1(T->rightchild);//访问右子结点
}
}
void PostOrderTraverse1(BinaryTree T)//先序遍历递归实现
{
if(T)
{
PostOrderTraverse1(T->leftchild);//访问左子结点
PostOrderTraverse1(T->rightchild);//访问右子结点
cout<<T->data<<" ";//访问根结点
}
}
void PreOrderTraverse2(BinaryTree T)//先序遍历非递归实现
{
stack<BinaryTree> s;
while(!s.empty()||T)
{
while(T)
{
cout<<T->data<<" ";//访问根结点
s.push(T);//压入访问过的根结点
T=T->leftchild;//访问当前根结点的左子结点
}
//至此为止:所有栈内的结点及其左子结点均已访问完毕
T=s.top();//取出最后访问过的根结点
s.pop();//删除栈首元素
T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
}
}
void InOrderTraverse2(BinaryTree T)//中序遍历非递归实现
{
stack<BinaryTree> s;
while(!s.empty()||T)
{
while(T)
{
s.push(T);//压入根结点但不访问
T=T->leftchild;//将当前根结点的左子结点更新为新的根结点(如果存在的话)
}
//至此为止:所有栈内的结点的左子结点均已访问完毕
T=s.top();//取出最后压入的根结点(该根结点的左子结点为空)
cout<<T->data<<" ";//访问该根结点
s.pop();//栈首元素出栈
T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
}
}
void PostOrderTraverse2(BinaryTree T)//后序遍历非递归实现
{
//后序遍历中,二叉树的根结点需要其左右子树都遍历结束后才能访问,需要两个栈来辅助解决
stack<BinaryTree> s;//指针栈来存放所经过的根结点的指针
stack<int> num;//辅助栈用来记录某根结点被路过的次数
while(T||!s.empty())
{
while(T)
{
s.push(T);//压入根结点不访问
num.push(1);//第一次路过该根结点
T=T->leftchild;//将当前根结点的左子结点更新为新的根结点(如果存在的话)
}
if(!num.empty())//辅助栈非空时
{
if(num.top()==1)
{
num.top()=2;//第二次路过当前根结点
T=s.top();//取出该根结点
T=T->rightchild;//将当前根结点的右子结点更新为新的根结点(如果存在的话)
}
else//第三次路过该当前根结点
{
T=s.top();//取出根结点
s.pop();//指针栈删除栈首元素
num.pop();//辅助栈删除栈首元素
cout<<T->data<<" ";//访问当前根结点
T=NULL;//将访问过的结点置空
}
}
}
}
二叉树前中后序遍历的递归版本和非递归版本、队列实现的层次遍历
最新推荐文章于 2020-09-12 16:08:28 发布