二叉树的遍历


 善于利用之前的轮子:将半线性的二叉树转换成线性结构

  


 


一、先序遍历

  递归格式:

   递归栈中的每一帧都是具有通用格式的,但显然当递归到深处时,帧的格式应该足够小。

 将递归格式转换为栈格式:

  

 迭代的思路如下所示: 沿着左侧链(总是沿着左侧孩子分支不断下行的一条链)不断展开

  

先序遍历:顶而下的依次访问左侧链上的节点,然后再自下而上的依次遍历各个层次上的每一颗右子树:

  

 代码实现:

  

 主算法:

  

 实例:

  


二、中序遍历

  先访问左侧子树,再访问根节点,再访问右侧子树。中序遍历要比左序遍历略难,因为在中序遍历中对右子树的访问还是尾递归调用,但是对左子树的调用不是尾递归调用。

 

 观察规律:

   

 节点访问次序:整个左侧链有多长,就有多少个阶段,访问左侧链节点,遍历右子树,不断重复这个过程。从根出发沿左分支下行,直到最深的节点——它就是全局首先被访问者。(采用某种后进先出的结构

 

 代码实现:

 

 实例:

  • 先引入一个栈,初始为空。算法的入口在这棵树的树根,节点b并不会被立即访问,而是沿着左侧链不断下行直到末端节点a,从第一个遇到的b到最后遇到的a都将被推入到栈中
  • 先让a出栈,访问a,然后将控制权交给a的右孩子,但是右孩子并不存在,但是也会调用goAlongLeftBranch,但是只是过门,并不会访问。此后b出栈,访问b,然后将控制权转让给b的右孩子。
  • 依次重复。

 性能分析:

  迭代版本的运行时间仍然是O(n),虽然迭代版本的运行时间也是O(n),但是从常系数的意义来讲,其远胜于递归版本。分摊分析法

 


 三、后序遍历

  后序遍历是先访问左侧子树,再再访问根节点。

代码如下:  

  

图示如下:

 

 先创建一个空的栈,算法入口是根节点,然后

  

 

 


 三、层次遍历

  从高到低、从左到右。严格按照深度次序来遍历访问。无论先序、中序、后序都可能出现子节点先于父节点访问,而在层次遍历中,严格要求按深度从上到下访问,所以使用队列这种数据结构。

  

 借助队列来实现层次遍历:

  


 二叉树重构:

  只需要中序遍历序列一次再加上先序或后序遍历一次,就可以重构整个二叉树的拓扑结构。

陈小洁的三只猫
原文地址:https://www.cnblogs.com/ccpang/p/11451188.html