个人感觉后序遍历真的比前序遍历与中序遍历的非递归方式麻烦好多,上一篇文章写完后思考了好久。写了好几次死循环。。。。今天参考了别人的代码才写出来。
链接如下:
https://blog.csdn.net/happyjacob/article/details/83116702
#include <bits/stdc++.h>
using namespace std;
typedef char Elemtype;
typedef struct BitNode{ //树节点
Elemtype data;
BitNode *lchild,*rchild;
}BitNode,*BitTree;
/**
二维指针
前序插入初始化
*/
void createBiTree(BitTree *tree){
char c;
scanf("%c",&c);
if(c=='#'){
*tree=NULL;
}else{
*tree=new BitNode; //分配指针存储空间
(*tree)->data=c;
createBiTree(&(*tree)->lchild);
createBiTree(&(*tree)->rchild);
}
}
/**
递归遍历(前序)
*/
void printBiTreeone1(BitTree &p){
if(p){
printf("%c",p->data);
printBiTreeone1(p->lchild);
printBiTreeone1(p->rchild);
}
}
/**
递归遍历(后序)
*/
void printBiTreeone2(BitTree &p){
if(p){
printBiTreeone2(p->lchild);
printBiTreeone2(p->rchild);
printf("%c",p->data);
}
}
/**
非递归遍历,前序
*/
void printBiTree2(BitTree &p){
stack<BitTree> stk;
BitTree node=new BitNode; //分配内存
while(p||!stk.empty()){ //stk.empty() 非为false,空为true
if(p!=NULL){
node=p;
stk.push(node);
printf("%c",node->data);
p=p->lchild;
}else{
node=stk.top();
stk.pop();
p=node->rchild;
}
}
}
/**
非递归遍历,后序:
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。
如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,
则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,
这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
*/
void printBiTree3(BitTree &p){
stack<BitTree> stk;
BitTree cur=p,pre=NULL; //分配内存
if(p!=NULL) stk.push(p);
while(!stk.empty()){ //stk.empty() 非空为false,空为true
cur=stk.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
((pre==cur->lchild||pre==cur->rchild)&&pre!=NULL))
{
cout<<cur->data;
stk.pop();
pre=cur;
}else{
if(cur->rchild!=NULL){
stk.push(cur->rchild);
}
if(cur->lchild!=NULL){
stk.push(cur->lchild);
}
}
}
}
int main(){
BitNode *p=NULL;
createBiTree(&p);
printBiTreeone2(p); //递归
cout<<endl;
printBiTree3(p); //非递归
return 0;
}