二叉树的三种遍历方式(递归与非递归)
一. 二叉树
1.1 二叉树的定义
#include<bits/stdc++.h>
using namespace std;
char ch;
typedef char Elemtype;
typedef struct BiTNode{
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
1.2 创建二叉树
//先序序列存入
void CreateBiTree(BiTree &T){
cin>>ch;
if(ch=='\n')
return;
if(ch=='#')
T=NULL;
else{
T=(BiTree)malloc(sizeof(BiTNode));
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
二. 递归解法
采用先序遍历存入结点信息。
2.1 前序遍历
遍历顺序:根结点——左子树——右子树
//前序遍历二叉树
void PreOrder(BiTree T){
if(T!=NULL){
cout<<T->data;
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
2.2 中序遍历
遍历顺序:左子树——根结点——右子树
//中序遍历二叉树
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
cout<<T->data;
InOrder(T->rchild);
}
}
2.3 后序遍历
遍历顺序:左子树——右子树——根结点
//后序遍历二叉树
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
cout<<T->data;
}
}
2.4 主函数
int main(){
BiTree T;
CreateBiTree(T);
//前序遍历
PreOrder(T);
cout<<endl;
//中序遍历
InOrder(T);
cout<<endl;
//后序遍历
PostOrder(T);
return 0;
}
三. 非递归解法
采用先序遍历存入结点信息。
核心思路为:利用栈存储遍历经过的结点。
3.1 前序遍历
遍历顺序:根结点——左子树——右子树
//前序遍历二叉树
void PreOrder(BiTree T){
//定义栈
stack<BiTree> s;
BiTree p=T;
while(p!=NULL||!s.empty()){
//遍历左子树
//用栈记录经过的结点
while(p!=NULL){
cout<<p->data;
s.push(p);
p=p->lchild;
}
//遍历完左子树时,若栈里边还有结点
//则退栈,后退到跟结点,并且向右支前进
//此时p!=NULL,会进入以上while循环
if(!s.empty()){
p=s.top();
s.pop();
p=p->rchild;
}
}
}
/*在 if(!s.empty())中,当获得右支指针后,
将根结点从栈中弹出,以便返回的时候直接回到祖先结点*/
3.2 中序遍历
遍历顺序:左子树——根结点——右子树
//中序遍历二叉树
void InOrder(BiTree T){
//定义栈
stack<BiTree> s;
BiTree p=T;
while(p!=NULL||!s.empty()){
//遍历左子树
while(p!=NULL){
s.push(p);
p=p->lchild;
}
//遍历完左子树时,若栈里边还有结点
//则退栈,后退到根结点,往右支前进
//此时p!=NULL,会进入以上while循环
if(!s.empty()){
p=s.top();
s.pop();
//退栈时,访问根节点
cout<<p->data;
p=p->rchild;
}
}
}
3.3 后序遍历
遍历顺序:左子树——右子树——根结点
//后序遍历二叉树
void PostOrder(BiTree T){
//定义栈
stack<BiTree> s;
BiTree p=T,r=NULL; //r为临时节点
while(p!=NULL||!s.empty()){
//最左边
if(p!=NULL){
s.push(p);
p=p->lchild;
}
else{
p=s.top();
//右子树存在且未被访问
if(p->rchild!=NULL&&p->rchild!=r){
p=p->rchild;
}
else{
s.pop();
cout<<p->data;
r=p; //记录最近访问过的节点
p=NULL; //节点访问完后,重置p指针
}
}
}
}
/*使用辅助指针r,其指向最近访问过的节点。
也可以在节点中增加一个标志域,记录是否已被访问*/
3.4 主函数
int main(){
BiTree T;
CreateBiTree(T);
//前序遍历
PreOrder(T);
cout<<endl;
//中序遍历
InOrder(T);
cout<<endl;
//后序遍历
PostOrder(T);
return 0;
}