树的前序后序中序遍历

7 篇文章 1 订阅

http://www.cnblogs.com/LZYY/p/3454778.html

在计算机科学里,树的遍历是指通过一种方法按照一定的顺序访问一颗树的过程。

对于二叉树,树的遍历通常有四种:先序遍历、中序遍历、后序遍历、广度优先遍历。(前三种亦统称深度优先遍历)对于多叉树,树的遍历通常有两种:深度优先遍历、广度优先遍历。

 

在学习前面三种深度优先遍历之前,很有必要了解它们之间到底是怎么遍历的,要自己去亲自去遍历,不要只看文字

 

先序遍历:  节点 - 左孩子 - 右孩子

中序遍历: 左孩子  - 根结点 - 右孩子

后序遍历 : 左孩子 - 右孩子 - 根结点

 

看下面的图(自己去写出几种遍历的情况):

 

按照上面的三种方法去遍历,结果是

前序遍历:- + a * b – c d / e f
中序遍历:a + b * c – d – e / f
后序遍历:a b c d – * + e f / -

 

广度优先遍历,又叫层次遍历:从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。

在这幅图里所的结果是:- + / a * c f b – c d

 

下面给出java实现上面几种遍历的算法以及解释:

三种递归的算法不说了,直接说非递归算法:

前序非递归实现 

节点 - 左孩子 - 右孩子
     1)访问结点P,并将结点P入栈;
     2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
     3)直到P为NULL并且栈为空,则遍历结束。 

有两种实现方法:

 View Code

 

中序非递归算法:

  左孩子  - 根结点 - 右孩子
     *访问任意一节点p,若其左孩子非空,p入栈,且p的左孩子作为当前节点,然后在对其进行同样的处理
     *若其左孩子为空,则输出栈顶点元素并进行出栈操作,访问该栈顶的节点的右孩子
     *直到p为null并且栈为空则遍历结束
   (和前序的非递归算法1_1有相似之处)

 View Code

 

后序非递归算法

左孩子 - 右孩子 - 根结点

这个有难度  因为要保证左孩子和右孩子都已经被访问过了才访问根节点,这里就要思考一下如何标记一下右孩子是否已经被标记了。有两种方法:

 

双栈法(这个比较容易理解)
     * 对于跟节点t,先入栈,然后沿着其左子树往下收索,直到没有左子树的节点,此时该节点入栈
     * 但此时不能进行出栈访问,要检查右孩子,所以接下来一相同的规则进行处理,当访问其右孩子时,
     * 该节点又出现在栈顶,此时就可以出栈访问,这样就保证了正确的访问顺序,这个过程中,
     * 每个节点都两次出现在栈顶,只有在第二次出现在栈顶的时候才能访问它, 因此有必要设置两个栈

 View Code

 

单栈法:

     * 先扫描跟节点的所有左节点并入栈,接着将栈顶元素出栈,
     * 再扫描该节点的右孩子节点并入栈,扫描右孩子的所有左节点并入栈,当一个节点的左右孩子均被访问后在访问该节点,
     * 这里用一个初始值为null的节点表示右子树刚刚被访问的
     * 一直到栈为空,这里的难点是如何判断右孩子已经被访问过了
     这个构造真的是太赞了!!

 View Code

 

另外一个单栈实现,单栈的构造都好神奇!

 View Code

 

如果用数组去实现stack的话,可以用这个,这个是在求解两节点个最近公共祖先时用到的(LCA算法),改写自考研书上

 View Code

 

下面是全部的代码外加一个测试实例:

 View Code

 

网上有好的很好的文章都有写道这几个搜索算法,这个博客是用c++实现的

http://www.blogjava.net/fancydeepin/archive/2013/02/03/cpp_binarytreesearch.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值