递归实现
typedef struct BiTNode
{
char data;
BiTNode *lc, *rc;
} BiTNode, *BiTree;
/*先序遍历*/
void PreOrderTraverse(const BiTree T)
{
if (T)
cout << T->data;
else
return;
PreOrderTraverse(T->lc);
PreOrderTraverse(T->rc);
}
/*中序遍历*/
void InOrderTraverse(const BiTree T)
{
if (T == NULL)
return;
InOrderTraverse(T->lc);
cout << T->data;
InOrderTraverse(T->rc);
}
/*后序遍历*/
void PostOrderTraverse(const BiTree T)
{
if (T == NULL)
return;
PostOrderTraverse(T->lc);
PostOrderTraverse(T->rc);
cout << T->data;
}
非递归实现
typedef struct BiTNode
{
char data;
BiTNode *lc, *rc;
} BiTNode, *BiTree;
/*先序遍历*/
void PreOrderTraverse(const BiTree T)
{
stack<BiTree> s;
BiTree p = T;
while (p || !s.empty())
{
if (p)
{
cout << p->data;
s.push(p);
p = p->lc;
}
else
{
p = s.top();
s.pop();
p = p->rc;
}
}
}
/*中序遍历*/
void InOrderTraverse(const BiTree T)
{
stack<BiTree> s;
BiTree p = T;
while (p || !s.empty())
{
if (p)
{
s.push(p);
p = p->lc;
}
else
{
p = s.top();
s.pop();
cout << p->data;
p = p->rc;
}
}
}
/*后序遍历*/
void PostOrderTraverse(const BiTree T)
{
stack<BiTree> s;
BiTree p = T;
BiTree q = NULL;
while (p || !s.empty())
{
if (p)
{
s.push(p);
p = p->lc;
}
else
{
p = s.top();
if (p == q)
{
cout << p->data;
s.pop();
p = NULL;
if (!s.empty() && s.top()->rc == q)
q = s.top();
}
else
{
q = p;
p = p->rc;
}
}
}
}
对非递归遍历实现的理解:
非递归实现实际上是对递归的深刻理解后得出的,首先看先序遍历和中序遍历的非递归实现,cout是访问过程,而s.push(p),p=p->lc,两句话相当于以p->lc为参数调用递归函数。仔细观察这个过程发现完全是在模拟递归函数的调用,调用递归函数时指令地址和函数参数入栈,s.push(p),p=p->lc执行完成再重新开始循环时,与以调用p->lc为参数的函数具有相同的行为。当从栈中弹出p,则相当于回到原函数中。与递归不同的是,当我们发现p为NULL时直接将栈顶元素弹出,这是因为先序和中序遍历已经完成了对栈顶元素的访问,不需要等到其调用完右子树递归再弹出。
而后序遍历则稍微复杂一些,由于后序遍历需要完成对其左子树和右子树的遍历后再访问该节点,于是用一个节点变量来记录最近已经完成左右子树遍历的节点。当从栈顶取出的元素完成左右子树的遍历后则将其从栈中弹出并访问。