树的先序、中序、后序遍历非递归实现

来源:互联网 发布:云计算和超级计算机 编辑:程序博客网 时间:2024/04/30 21:20
1. 树的后序遍历

对照《将递归函数转换为非递归形式》的“5. 去掉goto后优化的非递归实现步骤”,可以实现树的后序遍历非递归函数:

enum Tags{ROOT,LEFT,RIGHT};                         //Tags对应《将递归函数转换为非递归形式》提到的rdtemplate<typename Comparable>class ELEM{public:    typename BinarySearchTree<Comparable>::_BinaryNode* point;    Tags tag;};template<typename Comparable>void BinarySearchTree<Comparable>::postOrderTraverStack(BinaryNode* t)const{    std::stack<ELEM<Comparable> > s;    ELEM<Comparable> element,tmp;    tmp.point = t;    tmp.tag = ROOT;    s.push(tmp);                                    // 步骤(1):对根节点压栈    do    {        while( (element = s.top()).point != NULL)   //步骤(2):对根节点不断向下搜索,直到满足递归出口条件。这里的出口条件为:element.pointer = NULL        {            tmp.point = element.point->left;            tmp.tag = LEFT;            s.push(tmp);        }                                                   //因为对于出口条件element.point == NULL,不需要做任何操作,所以步骤(3)省略        while( (element = s.top()).tag == RIGHT)   //步骤(4):如果当前节点是父节点最后一个节点,则不断上溯,直到找到不是父节点最后一个节点的祖先节点        {            s.pop();            element = s.top();            (element.point)->visit();        }        if( (element = s.top()).tag == LEFT)       //步骤(5):如果当前节点不是父节点最后一个节点,把兄弟节点压栈        {            s.pop();            element = s.top();            tmp.point = element.point->right;            tmp.tag = RIGHT;            s.push(tmp);        }    }while( (element = s.top()).tag != ROOT); //步骤(4)上溯的过程可能到达根节点。    s.pop();}
2. 树的先序遍历、中序遍历简化处理

我们同样也可以严格按照上面的步骤写出先序遍历和中序遍历的非递归函数。不过由于先序遍历和中序遍历递归函数调用了最后一个递归子函数(右节点)后不需要再对当前函数进行相关处理,也就是说左节点处理完后,可以将左节点和父节点先从堆栈中删除,然后再对右节点入栈,这样右节点就占据了父节点的位置。具体见下面两幅图,图2将图1的C1、 D1删除只剩下D2,这时相当于D2占据了父节点C1的位置,由于C1是B1的左节点,所以将C1、 D1删除后新压入栈的D2一定是它的新回溯节点B1的左节点。所以就不用再考虑步骤(4)了。从而简化了递归到非递归的转换过程。
图1
这里写图片描述

3. 先序遍历非递归代码:
template<typename Comparable>void BinarySearchTree<Comparable>::preOrderTraverStack(BinaryNode* t)const{    std::stack<BinaryNode*> s;               s.push(t);    BinaryNode* p = NULL;                //步骤(1):对根节点压栈    while(!s.empty())                 {        while( (p = s.top()) != NULL)   //步骤(2):不断遍历左节点,直到空(空为递归出口)                   {            p->visit();                 //访问当前节点            s.push(p->left);            }                                       //后面分两种情况:栈顶节点或为左节点或为根节点。        s.pop();                       //空节点不需要做任何事情仅pop掉即可         if(!s.empty())                 //若之前的栈顶节点是根节点这里栈空,函数结束;若为左节点,后面的语句进行步骤(5)处理        {                              //步骤(5):处理当前节点不是父节点最后一个节点即为左节点的情况            p = s.top();                         s.pop();                  //**右节点入栈前先删除父节点**            s.push(p->right);           }    }                              }
4. 中序遍历非递归代码:
template<typename Comparable>void BinarySearchTree<Comparable>::inOrderTraverStack(BinaryNode* t)const{    std::stack<BinaryNode*> s;    s.push(t);    BinaryNode* p = NULL;    while(!s.empty())    {        while( (p = s.top()) != NULL)        {            s.push(p->left);        }        s.pop();        if(!s.empty())        {            p = s.top();            p->visit();            s.pop();            s.push(p->right);        }    }}
5. 参考

《 将递归函数转换为非递归形式》

0 0
原创粉丝点击