数据结构定义:
struct Node {
char val;
pNode lchild, rchild;
};
二叉树形态:
A
/ \
B C
/ \ / \
D E F G
/ \
H I
前序遍历:
先判断节点的指针是否为空,不为空就先访问该结点,然后直接进栈,接着遍历左子树;为空则要从栈中弹出一个节点来,这个时候弹出的结点就是其父亲,然后访问其父亲的右子树,直到当前节点为空且栈为空时,算法结束.
void preVisitStack(pNode root)
{
stack<pNode> s;
pNode p = root;
while (p != NULL || !s.empty()) {
if (p != NULL) {
printf("%c ", p->val);
s.push(p);
p = p->lchild;
}
else {
p = s.top();
s.pop();
p = p->rchild;
}
}
cout << endl;
}
中序遍历:
和先序遍历一样,但在访问节点的顺序不一样,访问节点的时机是从栈中弹出元素时访问,如果从栈中弹出元素,就意味着当前节点父亲的左子树已经遍历完成,这时候访问父亲,就是中序遍历.
void midVisitStack(pNode root)
{
stack<pNode> s;
pNode p = root;
while (p != NULL || !s.empty()) {
if (p != NULL) {
s.push(p);
p = p->lchild;
}
else {
p = s.top();
printf("%c ", p->val);
s.pop();
p = p->rchild;
}
}
cout << endl;
}
后序遍历:
后续遍历,首先访问左子树,把父亲节点保存于栈中,问题是当元素从栈中弹出的时候,我们无法判断这个时候是该访问其右子树还是访问父亲节点,于是我们就需要一个标记,当访问左子树时我们把父亲节点的标记设为1,表示下一步如果弹出该节点,就访问其右子树;弹出一个节点时,我们要判断该节点的标记,如果是1,则访问其右子树,并把该节点的标记设置成2,表示下一步就访问该节点,然后把该节点继续入栈,如果是2,那么表示访问该节点,访问并且丢弃该节点.
void backVisitStack(pNode root)
{
stack<pNode> s;
pNode p, q;
p = root;
q = NULL;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
if (p->rchild == NULL || p->rchild == q)
{
printf("%c ", p->val);
q = p;
s.pop();
p = NULL; //重要 避免死循环
}
else
{
p = p->rchild;
}
}
}
cout << endl;
}
测试代码:
#include <iostream>
#include <stack>
using namespace std;
typedef struct Node *pNode;
struct Node {
char val;
pNode lchild, rchild;
};
void createBiTree(pNode &T)
{
char c;
cin >> c;
if ('#' == c)
T = NULL;
else
{
T = new Node;
T->val = c;
createBiTree(T->lchild);
createBiTree(T->rchild);
}
}
void preVisitStack(pNode root)
{
stack<pNode> s;
pNode p = root;
while (p != NULL || !s.empty()) {
if (p != NULL) {
printf("%c ", p->val);
s.push(p);
p = p->lchild;
}
else {
p = s.top();
s.pop();
p = p->rchild;
}
}
cout << endl;
}
void midVisitStack(pNode root)
{
stack<pNode> s;
pNode p = root;
while (p != NULL || !s.empty()) {
if (p != NULL) {
s.push(p);
p = p->lchild;
}
else {
p = s.top();
printf("%c ", p->val);
s.pop();
p = p->rchild;
}
}
cout << endl;
}
void backVisitStack(pNode root)
{
stack<pNode> s;
pNode p, q;
p = root;
q = NULL;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.top();
if (p->rchild == NULL || p->rchild == q)
{
printf("%c ", p->val);
q = p;
s.pop();
p = NULL; //重要 避免死循环
}
else
{
p = p->rchild;
}
}
}
cout << endl;
}
int main()
{
Node* root;
createBiTree(root);
printf("先序遍历:");
preVisitStack(root);
printf("中序遍历:");
midVisitStack(root);
printf("后序遍历:");
backVisitStack(root);
system("pause");
}
测试输入:ABD##E##CFH##I##G##
测试结果:
前序遍历: A B D E C F H I G
中序遍历: D B E A H F I C G
后序遍历: D E B H I F G C A