二叉树后序遍历的非递归算法

首次写博客,不知道有什么社区规矩没,不当之处请指正。

 

看到书上二叉树后序遍历的非递归算法需要一个退栈标记,不太喜欢这种做法,就尝试自己写了一下,验证了几次,遍历顺序都是对的,下面贴代码,若有细微难以发现的错误之处,还请诸位多多指教,本人初学算法,水平实在不咋地。。。。

 

 1     LinkStack<TreeNode<T>*> stack;    //自己写的链式栈
 2     TreeNode<T>* p = subTree;
 3     stack.push(p);//根节点入栈
 4     while(!stack.isEmpty())
 5     {
 6         if(p->leftChild == NULL && p->rightChild == NULL)//如果是叶节点,即访问之
 7         {
 8             visit(p);
 9             stack.pop();
10             if(!stack.isEmpty() && (stack.getTop().data ->leftChild == p || stack.getTop().data->rightChild == p))
11             //如果退栈后的栈顶是原栈顶的父节点,继续退栈
12             {
13                 while(!stack.isEmpty() && (stack.getTop().data ->leftChild == p || stack.getTop().data->rightChild == p))
14                 {
15                     p = stack.getTop().data;
16                     visit(p);
17                     stack.pop();
18                 }
19                 if(!stack.isEmpty())
20                     p = stack.getTop().data;
21             }
22             else
23                 if(!stack.isEmpty())
24                     p = stack.getTop().data;
25         }
26         else//如果是非叶节点,即按照右子树,左子树的顺序进栈
27         {
28             if(p->rightChild != NULL)
29             {
30                 stack.push(p->rightChild);
31             }
32             if(p->leftChild != NULL)
33             {
34                 stack.push(p->leftChild);
35             }
36             p = stack.getTop().data;
37         }
38     }


总体的思想是:

  1. 后序遍历是先左子树,后右子树,最后根节点;每访问到一个节点,节点先如果非叶节点,按照右子树,左子树的顺序入栈,必能保证退栈时先访问左子树,然后右子树。
  2. 当首次循环到最左边的叶节点时,开始访问并退栈,并将退出的元素与新的栈顶比较;按照1中的顺序,如果新的栈顶不是退栈元素的父节点,只能是父节点的右子树,循环指针指向栈顶继续右子树的入栈操作(如果有的话);如果栈顶是退栈元素的父节点,表明此父节点的元素已经遍历完(有可能是右子树退回去的,也有可能是没有右子树,总之是遍历完了),可以访问此节点并继续退栈,如此循环。
  3. 对于根节点要特别注意,每次都要判断是不是栈空了,否则会有问题。

 

posted on 2015-12-04 15:25  cestlav  阅读(808)  评论(0)    收藏  举报

导航