二叉树在面试中很容易被问到,三种遍历的非递归版本,最近就遇到了二叉树的后续非递归遍历,所以我就将二叉树的后续非递归遍历实现了一下,代码如下:
/*二叉树的后续非递归遍历*/
//二叉树节点的结构,我使用模板实现的,这样复用性较好
template<class T>
struct BinTreeNode
{
T _value;
BinTreeNode<T>* left;
BinTreeNode<T>* right;
BinTreeNode(const T& val)
: _value(val)
, left(NULL)
, right(NULL)
{}
};
#include <stack> //当然一般是在头文件中引入的,但是这里只是实现一个函数,所以就在函数前面引入一下
template<class T>
void PostOrder(BinTreeNode<T>* t)
{ //t是树的根节点
assert(t); //判断t是否合法
stack<BinTreeNode<T>*> S; //使用stack来实现非递归后续遍历
BinTreeNode<T>* cur = t;
BinTreeNode<T>* visitedNode = NULL; //标记已经被访问的节点,用于标记右边的节点被访问过
while (cur || !S.empty())
{
// 当前节点不为空,一直压栈,切不断往左子树深入
while (cur)
{
S.push(cur);
cur = cur->left;
}
//左子树为NULL时停止,这就是左子树为NULL的情况
t = S.top(); //取栈顶元素
/*
*右孩子为空或被访问过则输出,而且当以下两个条件满足时才能输出当前节点,其中
* t->right == NULL说明该节点没有右子树了,该节点需要被打印;
*t->right == visitedNode时说明右子树已经遍历过,满足后续遍历要求。
*/
if (t->right == NULL || t->right == visitedNode)
{
cout << t->_value << " ";
S.pop();
visitedNode = t; //标记该节点被访问过
}
else
{ //说明该节点还存在右子树,我们应该去右子树中寻找下一个打印的节点
cur = t->right;
}
}
}