#include<bits/stdc++.h>
using namespace std;
typedef struct TNode{
char data;
struct TNode *Left;
struct TNode *Right;
}TNode,*Tree;
void Precreat(Tree &T){ //如果不加引用则会产生临时变量T,而不是原来的地址
char c;
scanf("%c" , &c);
if(c == '#')T = NULL;
else{
T = new TNode;
T->data = c;
Precreat(T->Left);
Precreat(T->Right);
}
}
void InTravel_withoutRecursion(Tree T){
/*把每个节点都当作根节点来对待,即当访问到该节点时只需查看右子树是否为空即可,
若为空则进行出栈,若不为空则将右子树进行入栈并进行遍历,因为当访问到根节点时表
明该节点的左子树已经访问完了,因此将该节点进行出栈,并接着访问右子树即可--->访
问每个节点时都为访问根节点*/
stack<TNode>stk;
TNode *p = T;
while(p != NULL || !stk.empty()){
while(p){
stk.push(*p);
p = p->Left;
}
if(!stk.empty()){
p = &stk.top();
stk.pop();
cout<<p->data;
p = p->Right;
}
}
cout<<endl;
}
void PreTravel_withoutRecursion(Tree T){ //边遍历遍输出
/*在栈里面的都是已经遍历过且输出过但右节点还未遍历过的*/
stack<TNode> stk;
TNode *p = T;
while(p != NULL || !stk.empty()){
while(p){
cout<<p->data;
stk.push(*p);
p = p->Left;
}//当P为空时说明延左路径走到头了
if(!stk.empty()){ //节点右移
p = &stk.top();
stk.pop();
p = p->Right;
}
}
cout<<endl;
}
void PostTravel_withoutRecursion(Tree T){
stack<TNode*> stk;
TNode *p = T;
TNode *pastvis = NULL;
while(p){ //找到由根节点开始最左侧的节点,并将左侧的节点依次入栈.
stk.push(p);
p = p->Left;
}
while(!stk.empty()){
p = stk.top(); //从栈中依次取出节点作为根节点
stk.pop(); //若该节点的右子树已经访问过或者为空即可访问该节点的根节点
if(p->Right == NULL || p->Right == pastvis){
cout<<p->data;
pastvis = p;
}
else{ //对if的调节取反根据逻辑运算可得当右侧有节点且未被访问过时访问右子树
stk.push(p);
p = p->Right; //对取出的根节点先入栈(暂时还访问不到)
while(p){ //右子树进行的左侧进行入栈操作,手动操作一个递归
stk.push(p);
p = p->Left;
}
}
}
cout<<endl;
}
int main(){
Tree T;
Precreat(T); //即使Tree为指针型变量,但若不添加引用,则传递的仍然为形参而不是实参
PostTravel_withoutRecursion(T); //后序遍历
PreTravel_withoutRecursion(T); //先序遍历
InTravel_withoutRecursion(T); //中序遍历
}
感谢大佬博客的启发:http://blog.youkuaiyun.com/zhangxiangdavaid/article/details/37115355