整体思路:用两个栈分别记录节点和正在遍历的子树,在适当的时候输出。
对三种遍历方式来说区别只在于什么时候输出。
遍历
遍历的方法很简单,就是根据记录的节点的正在遍历的子树来决定推入的是哪个子节点。当一个节点的两个子树都遍历完全时就把节点从栈中去掉,顺便改一下父节点记录的正在遍历的子树(毕竟一个子树遍历完了)
以前序遍历的代码为例:
void preorder(PNode T)
{
stack<PNode> S;//记录正在遍历的节点
stack<int> state;//1代表正在遍历左子树,2代表正在遍历右子树,3表示该节点的所有子树已经遍历完全该弹出了
S.push(T);
state.push(1);
cout<<T->val<<" ";
while(true)
{
//取栈顶元素
PNode N=S.top();
int s=state.top();
if(s==1)
{
if(N->left!=nullptr)
{
cout<<N->left->val<<" ";
S.push(N->left);
state.push(1);//下一个该遍历该节点的左子树了
}
else
{
//左子树为空,接下来开始遍历右子树
state.pop();
state.push(2);
}
}
else if(s==2)
{
if(N->right!=nullptr)
{
cout<<N->right->val<<" ";
S.push(N->right);
state.push(1);
}
else//右子树为空,该节点的所有子树遍历完全,更改记录
{
state.pop();
state.push(3);
}
}
else if(s==3)
{
//该节点的所有子树都遍历过了
state.pop();
S.pop();
if(S.empty()) break;//栈空了,已经遍历一遍,可以退出循环
//更改父节点的记录
s=state.top();
state.pop();
state.push(s+1);
}
}
}
输出:
前序遍历:在遍历左子树前输出
中序边历:左子树遍历完全后输出
中序遍历的代码:
void Midorder(PNode T)
{
stack<PNode> S;
stack<int> state;//1代表正在遍历左子树,2代表正在遍历右子树,3表示子树已经遍历完全该弹出了
int decision=1;
S.push(T);
state.push(1);
while(true)
{
PNode N=S.top();
int s=state.top();
if(s==1)
{
if(N->left!=nullptr)
{
S.push(N->left);
state.push(1);
}
else
{
cout<<N->val<<" ";//没有左子树,输出
state.pop();
state.push(2);
}
}
else if(s==2)
{
if(N->right!=nullptr)
{
S.push(N->right);
state.push(1);
}
else
{
state.pop();
state.push(3);
}
}
else if(s==3)
{
state.pop();
S.pop();
if(S.empty()) break;
s=state.top();
if(s==1)//左子树遍历完,输出
{
N=S.top();
cout<<N->val<<" ";
}
state.pop();
state.push(s+1);
}
}
}
全部代码:
#include <iostream>
#include<vector>
#include<algorithm>
#include<stack>
#define datatype double
using namespace std;
//定义节点
typedef struct Node{
Node* right;
Node* left;
datatype val;
}Node,*PNode;
//中序遍历
void Midorder(PNode T)
{
stack<PNode> S;
stack<int> state;//1代表正在遍历左子树,2代表正在遍历右子树,3表示子树已经遍历完全该弹出了
int decision=1;
S.push(T);
state.push(1);
while(true)
{
PNode N=S.top();
int s=state.top();
if(s==1)
{
if(N->left!=nullptr)
{
S.push(N->left);
state.push(1);
}
else
{
cout<<N->val<<" ";
state.pop();
state.push(2);
}
}
else if(s==2)
{
if(N->right!=nullptr)
{
S.push(N->right);
state.push(1);
}
else
{
state.pop();
state.push(3);
}
}
else if(s==3)
{
state.pop();
S.pop();
if(S.empty()) break;
s=state.top();
if(s==1)
{
N=S.top();
cout<<N->val<<" ";
}
state.pop();
state.push(s+1);
}
}
}
//前序遍历
void preorder(PNode T)
{
stack<PNode> S;
stack<int> state;//1代表正在遍历左子树,2代表正在遍历右子树,3表示子树已经遍历完全该弹出了
int decision=1;
S.push(T);
state.push(1);
cout<<T->val<<" ";
while(true)
{
PNode N=S.top();
int s=state.top();
if(s==1)
{
if(N->left!=nullptr)
{
cout<<N->left->val<<" ";
S.push(N->left);
state.push(1);
}
else
{
state.pop();
state.push(2);
}
}
else if(s==2)
{
if(N->right!=nullptr)
{
cout<<N->right->val<<" ";
S.push(N->right);
state.push(1);
}
else
{
state.pop();
state.push(3);
}
}
else if(s==3)
{
state.pop();
S.pop();
if(S.empty()) break;
s=state.top();
state.pop();
state.push(s+1);
}
}
//cout<<"退出前序遍历"<<endl;
}
//后续遍历
void lastorder(PNode T)
{
if(T==nullptr) return;
lastorder(T->left);
lastorder(T->right);
cout<<T->val<<" ";
}