关于树的递归和迭代遍历方法

  最近在看csdn解题笔记系列文章关于树的部分,卒读之后,扪心自问:二叉树到底有多少种便利方法?每种方法又有几中实现版本?各个版本间的关系如何,有无必然联系和转化可能?那天知道晚上一点多才有一些确定性的思考结果,总结如下。

  一、树的递归遍历方法:略;

  二、树的非递归遍历方法

    (1)国内教材和网络流行的解法:二叉树的先根遍历,中根遍历,后根遍历的非递归算法 ;

    (2)自己凭直觉想了一种先序方法[1],但无法对称地推广到中序、后序,便随便翻了下师弟给的一本电子书,Knuth大弟子Sedgewick的《算法:第1-4部分》,发现一种新的,思路比较统一的先序、中序、后序遍历的形式化非递归法描述:

      1)对于根节点:
          对于前序,入栈右子树,然后左子树,然后节点;
          对于中序,入栈右子树,然后节点,然后左子树;
          对于后序,入栈节点,然后右子树,然后左子树;
      2)子树的入栈与上面是相同的,但是我们不使用递归;

  三、层次遍历,除了流行的队列法,我设计了一种基于栈的方法(其实在模拟队列),用伪代码描述,参见[2]。

  

  四、深入想下,递归和迭代的关系是什么?他们如何转化?

    首先,请看扫盲文:

      (1)尾递归对时间与空间复杂度的影响 ;

      (2)尾递归与Continuation ;

      (3)浅谈尾递归的优化方式 ;

    得到结论:只要允许使用栈(也有人叫基于栈的非递归为递推,不列入迭代范畴),所有的递归程序都可以转化成迭代,反之则不然。但是并非所有递归都必须用栈。深入学习请参考:将递归转化成迭代的通用技术 。

  五、附录:

    [1]

    root入栈

    tag:

      if (栈非空)

        弹一次栈x,访问之;

          if (x非叶子)

            x右子树入栈;

            x左子树入栈;

            goto tag;

      结束;

    [2]

    root入栈;

    if 栈(a,b,c...)非空

      连续弹栈,直至为空,得到出栈元素xi(...c,b,a);

    按出栈次序,访问xi;

    if(xi非叶子)

      xi右子树入栈;

      xi左子树入栈;

    结束;

 

  

posted @ 2012-05-02 13:19  aitao  阅读(2102)  评论(0编辑  收藏  举报