中序遍历非递归遍历算法
- 遇到一个结点,就把它压栈,并去遍历它的左子树;
- 当左子树遍历结束后,从栈顶弹出这个结点并访问它;
- 然后按其右指针再去中序遍历该结点的右子树。
观察可以发现,不管哪种遍历方式它走的路线都是一致的,关键在于在哪一次访问的时候进行输出。
前序遍历与中序遍历非常相似,前序入栈时即为第一次访问的时候,在这里输出。
后序遍历相对复杂:因为里面存在着一些访问次数为3的结点!
因此在出栈操作那个地方需要进行修改,这里把抛出条件分成两种情况:
- 没有右子树,可以直接抛出。
- 有右子树,且这个右子树已经抛出。(这个时候就是第三次访问这个结点)
完整代码如下:
#include <iostream>
#include <stack>
using namespace std;
typedef struct TreeNode* BinTree;
//typedef BinTree Position;
struct TreeNode {
char Data;
BinTree Left;
BinTree Right;
};
/*以前序遍历的形式输入来创建树*/
void CreatBinTree(BinTree& T)
{
char ch;
cin >> ch;
if (ch == '#') T = NULL;
else {
T = new struct TreeNode;
T->Data = ch;
CreatBinTree(T->Left);
CreatBinTree(T->Right);
}
}
void InOrderTraversal(BinTree BT)
{
BinTree t = BT;
stack<BinTree> s;
while (t || !s.empty())
{
while (t)
{
s.push(t);
t = t->Left;
}
if (!s.empty())
{
BinTree c = s.top();
s.pop();
cout << c->Data;
t = c->Right;
}
}
}
void PreOrderTraversal(BinTree BT)
{
BinTree t = BT;
stack<BinTree> s;
while (t || !s.empty())
{
while (t)
{
s.push(t);
cout << t->Data;
t = t->Left;
}
if (!s.empty())
{
BinTree c = s.top();
s.pop();
t = c->Right;
}
}
}
void PostOrderTraversal(BinTree BT)
{
BinTree t = BT;
BinTree Prev = NULL;
stack<BinTree> s;
while (t || !s.empty())
{
while (t)
{
s.push(t);
t = t->Left;
}
if (!s.empty())
{
BinTree c = s.top();
if (c->Right == NULL || Prev == c->Right)
//当它没有右节点时,或者右边的结点已经被访问过就可以抛出(输出)
{
cout << c->Data;
Prev = c;
s.pop();
}
else
t = c->Right;
}
}
}
bool IsEmpty(BinTree BT)
{
if (BT) return true;
else return false;
}
int main()
{
BinTree t;
//t = new struct TreeNode;
CreatBinTree(t);
InOrderTraversal(t);
cout << endl;
PreOrderTraversal(t);
cout << endl;
PostOrderTraversal(t);
return 0;
}