我们在实现二叉搜索树的先中后序遍历是一般的都是递归的来实现的,现在我们要实现其非递归的版本,核心思想是利用栈来模拟递归中的函数调用,自己来实现模拟递归
我们先来实现先序遍历————————————
void PreOrderNotRecursion(BinarySearchTree bst)//二叉查找数的非递归版先序遍历
{
std::stack<Position> s;
s.push(bst);
while(!s.empty())
{
Position pos = s.top();
s.pop();
std::cout<<pos->data<<"-";
if(NULL != pos->right)//如果pos有右儿子就先将其右儿子压入栈中
s.push(pos->right);
if(NULL != pos->left)//如果pos有左儿子就再将其左儿子压入栈中
s.push(pos->left);
}
}
然后实现中序遍历————————————————
void InOrderNotRecursion(BinarySearchTree bst)//二叉查找数的非递归版中序遍历,利用栈来模拟函数递归调用
{
std::stack<Position> s;
while(NULL != bst)//沿着最左的方向将左儿子依次压入栈中
{
s.push(bst);
bst = bst->left;
}
while(!s.empty())
{
Position pos = s.top();
s.pop();
std::cout<<pos->data<<"-";
if(NULL != pos->right)//pos has right child
{
pos = pos->right;
while(NULL != pos)//沿着最左的方向将左儿子依次压入栈中
{
s.push(pos);
pos = pos->left;
}
}
}
}
最后给出后序遍历,在这三个遍历中非递归后序遍历最难实现涉及到栈内的节点的二次访问控制————————
void PostOrderNotRecursion(BinarySearchTree bst)//二叉查找数的非递归版后序遍历
{
std::stack<Position> s;
std::set<Position> rchild_visited;
while(NULL != bst)//沿着最左的方向将左儿子依次压入栈中
{
s.push(bst);
bst = bst->left;
}
while(!s.empty())
{
Position pos = s.top();
//s.pop();
if(NULL == pos->right)//pos没有右儿子因此可以直接访问pos
{
std::cout<<pos->data<<"-";
s.pop();
}
else if(rchild_visited.find(pos) == rchild_visited.end())
{//pos有右儿子我们不可以访问pos,需要先访问完其右子树后才可访问pos
//因此要进入其右儿子中递归访问右子树同时标记pos的右儿子已经被我们访问过了
rchild_visited.insert(pos);
pos = pos->right;
while(NULL != pos)//把右子树的根连同其左儿子沿着左儿子的方向依次压入栈中
{
s.push(pos);
pos = pos->left;
}
}
else if(rchild_visited.find(pos) != rchild_visited.end())
{//此时pos右儿子已经被访问过了因此我们可以直接访问pos了
std::cout<<pos->data<<"-";
rchild_visited.erase(pos);
s.pop();
}
}
}