二叉树的非递归遍历需要用到栈,三种遍历方法中最麻烦的是后序遍历,因为它需要访问根结点2次,故在第一次访问的时候需要标示它的访问状态。
#include <iostream>
#include <stack>
using namespace std;
typedef struct _Tree{
int data;
struct _Tree *left;
struct _Tree *right;
} Tree;
typedef struct _Visit {
Tree *node;
bool visited; //访问标志
} Visit;
void PrePrintTree(Tree *root) {
if (NULL == root)
return;
Tree *p = root;
stack<Tree*> stk;
stk.push(p);
while (!stk.empty()) {
Tree *cur = stk.top();
stk.pop();
cout << cur->data << ' '; //先输出,再push右结点,push左结点(先pop左,再pop右,从而是先序遍历)
if (cur->right != NULL)
stk.push(cur->right);
if (cur->left != NULL)
stk.push(cur->left);
}
cout << endl;
}
void InPrintTree(Tree *root) {
if (NULL == root)
return;
Tree *p = root;
stack<Tree*> stk;
while (p != NULL) { //1. 一路将左结点push到栈中,相当于左结点优先处理过了
stk.push(p);
p = p->left;
}
while (!stk.empty()) {
Tree *cur = stk.top();
stk.pop();
cout << cur->data << ' '; //2. 输出中间结点
if (cur->right != NULL) { //3. 将右结点按步骤1处理
cur = cur->right;
while (cur != NULL) {
stk.push(cur);
cur = cur->left;
}
}
}
cout << endl;
}
void PostPrintTree(Tree *root) {
if (NULL == root)
return;
Tree *p = root;
stack<Visit> stk;
while (p != NULL) { //1. 一路将左结点push到栈中,相当于左结点优先处理过了
Visit v = {p, false};
stk.push(v);
p = p->left;
}
while (!stk.empty()) {
Visit cur = stk.top();
stk.pop();
//2. 当前结点是第一次访问,且有右结点没有处理,则修改访问标志,再次push当前结点
//然后按步骤1处理当前结点的右结点
if (cur.node->right != NULL && cur.visited == false) {
Visit v = {cur.node, true}; //修改访问标志为true,再次push当前结点
stk.push(v);
p = cur.node->right;
while (p != NULL) {
Visit v = {p, false};
stk.push(v);
p = p->left;
}
} else {
cout << cur.node->data << ' '; //3. 当前结点处理后,输出
}
}
cout << endl;
}
int main()
{
Tree a1 = {1, NULL, NULL};
Tree a2 = {2, NULL, NULL};
Tree a3 = {3, NULL, NULL};
Tree a4 = {4, NULL, NULL};
Tree a5 = {5, &a1, &a2};
Tree a6 = {6, &a3, &a4};
Tree a7 = {7, &a5, &a6};
PrePrintTree(&a7);
InPrintTree(&a7);
PostPrintTree(&a7);
return 0;
}
输出:
7 5 1 2 6 3 4
1 5 2 7 3 6 4
1 2 5 3 4 6 7