二叉树遍历算法

二叉树是树(Tree)这一数据结构中非常重要的子类,其中每一个节点最多存在两个子节点,在代码中表示就是,除了本身的 Data 值,还会带有 Left 和 Right 子节点。如下图所示,用形如图中的结构构成了整棵树。

任何一种数据结构,都会存在遍历的顺序问题,比如链表,堆栈等等;二叉树这种数据结构也有遍历的顺序,由于其非线性的结构特征,遍历时的顺序有这三种,前序(pre-order),中序(in-order),后序(post-order)。下面依次介绍一下:

1 前序(pre-order)遍历

基本的原则是“根 -> 左 -> 右”,重复直到整棵树的节点被浏览一遍。

1.1 Recursive 版本:

1 def preOrder( self, treenode ):
2     # Recursive version
3     if treenode == None:
4         return
5     print treenode.data
6     self.preOrder( treenode.left )
7     self.preOrder( treenode.right )

这段代码非常好理解,它就是用“根 -> 左 -> 右”的定义方式来写的,迭代调用,直至没有节点可以访问。

print treenode.data # 打印访问节点(根)的值
self.preOrder( treenode ) # 访问左子树
self.preOrder( treenode ) # 访问右子树

1.2 Non-recusive 版本:

 1 def preOrderN( self, treenode ):
 2     # Imperative version
 3     s = []
 4     while treenode is not None or len( s ) > 0:
 5         while treenode is not None:
 6             print treenode.data # 1
 7             s.append( treenode ) # 2
 8             treenode = treenode.left # 2
 9         if len( s ) > 0:
10             treenode = s.pop() # 3
11             treenode = treenode.right # 3

对于非递归版本,首先需要创建一个栈,用来保存需要树的节点,其遍历过程可以这样理解:每次操作由三部分组成:1. 获取当前节点(根)的值,2. 将根的所有左边节点放入栈中,3. 弹出此时的栈顶节点,如果它有右孩子的,将当前节点更新为它的右孩子节点。以上1,2,3,1,2,3...循环下去,直至没有节点可以访问。

2 中序(In-Order)遍历

基本的原则是“左 -> 根 -> 右”

2.1 Recursive 版本:

1 def inOrder( self, treenode ):
2     # Recursive version
3     if treenode == None:
4         return
5     self.inOrder( treenode.left )
6     print treenode.data
7     self.inOrder( treenode.right )

同样是以定义的方式来写的,将“访问左子树”、“获取根的值”、“访问右子树”以迭代的形式写成代码。

2.2 Non-recursive 版本:

 1 def inOrderN( self, treenode ):
 2     # Imperative version
 3     s = []
 4     while treenode is not None or len( s ) > 0:
 5         while treenode is not None:
 6             s.append( treenode ) # 1
 7             treenode = treenode.left # 1
 8         if len( s ) > 0:
 9             treenode = s.pop() # 3
10             print treenode.data # 2
11             treenode = treenode.right # 3

对于非递归版本,我们需要创建一个栈来保存需要树的节点,其遍历过程可以这样理解:每次操作由三部分组成:1. 将根的所有左边节点放入栈中,2. 获取当前节点(根)的值,3. 弹出此时的栈顶节点,如果它有右孩子的,将当前节点更新为它的右孩子节点。以上1,2,3,1,2,3...循环下去,直至没有节点可以访问为止。

3 后序(Post-Order)遍历

基本的原则是“左 -> 右 -> 根”

3.1 Recursive 版本

1 def postOrder( self, treenode ):
2     # Recursive version
3     if treenode == None:
4         return
5     self.postOrder( treenode.left )
6     self.postOrder( treenode.right )
7     print treenode.data

同样是以定义的方式来写的,将“访问左子树”、“访问右子树”、“获取根的值”写成迭代式的代码。

3.2 Non-recursive 版本

 1 def postOrderN( self, treenode ):
 2     # Imperative version
 3     s = []
 4     top = None
 5     pre = None
 6     while treenode is not None or len( s ) > 0:
 7         while treenode is not None:
 8             s.append( treenode ) # 1
 9             treenode = treenode.left # 1
10         if len( s ) > 0:
11             top = s[-1]
12             if top.right != None and top.right != pre:
13                 treenode = top.right # 3
14             else:
15                 print top.data # 2
16                 pre = top # 2
17                 s.pop() # 2

同样需要一个栈来保存树的节点,除此之外还需要一个 pre 记录右孩子的访问情况,过程是这样的:1. 将根的所有左边节点放入栈中,2. 如果栈顶节点的右孩子不存在,或者存在且被访问过,则可以获取当前节点(根)的值,3. 如果栈顶节点的右孩子存在且没被访问过,则进入当前的节点的右子树。以上1,2,3,1,2,3...循环下去,直至没有节点可以访问为止。

时间: 2024-12-06 00:25:11

二叉树遍历算法的相关文章

morris算法-----高级二叉树遍历算法

在遍历儿叉树时,常常使用的是递归遍历,或者是借助于栈来迭代,在遍历过程中,每个节点仅访问一次,所以这样遍历的时间复杂度为O(n),空间复杂度为O(n),并且递归的算法易于理解和实现.在遍历过程中,递归遍历过程的空间复杂度却是O(n),就算是转换为使用栈空间迭代时间,还是没有改变算法对额外空间的需求,在学习数据结构课程时,还学习了线索二叉树,在线索二叉树中,使用线索来保存节点的前驱和后继的信息,而这些线索是利用了叶节点的空指针域来保存,所以知道了树种每个节点的前驱和后继的位置(指针)可以有效降低遍

Binary Tree Traversal Algorithms (二叉树遍历算法)

本文共列出了11个常见的二叉树遍历算法.二叉树的遍历主要有深度优先遍历和广度优先遍历.深度优先遍历包含前序遍历.中序遍历和后序遍历. 值得一提的是, 其中的 Morris 算法 可以线性时间不需要额外空间(用户栈或系统栈空间)实现二叉树的前序遍历.中序遍历和后序遍历.关于Morris算法, 可参考 http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html 算法清单: A1. A2. A3, 分别是中序遍历的递归

二叉树遍历算法总结

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??二叉树遍历算法总结 ? ?? ? ?本文依据<数据结构与算法>(C语言版)(第三版) 整理. ? ?A. ?二叉树的遍历 ? ? ? 1.前序遍历二叉树: ? ? ? ? (1)若二叉树为空,则为空操作,返回空. ? ? ? ? (2)訪问根结点. ? ? ? ? (3)前序遍历左子树. ? ? ? ? (4)前序遍历右子树. ? ? ??a.

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

python实现二叉树遍历算法

说起二叉树的遍历,大学里讲的是递归算法,大多数人首先想到也是递归算法.但作为一个有理想有追求的程序员.也应该学学非递归算法实现二叉树遍历.二叉树的非递归算法需要用到辅助栈,算法着实巧妙,令人脑洞大开. 以下直入主题: 定义一颗二叉树,请看官自行想象其形状, class BinNode( ): def __init__( self, val ): self.lchild = None self.rchild = None self.value = val binNode1 = BinNode( 1

二叉树遍历算法——包含递归前、中、后序和层次,非递归前、中、后序和层次遍历共八种

首先,要感谢网上的参考资料. http://mengliao.blog.51cto.com/876134/1178079(作者:BlackAlpha) http://blog.csdn.net/fzh1900/article/details/14056735(作者:_云淡风轻) http://blog.csdn.net/stpeace/article/details/8138458(作者:stpeace) 二叉树是使用的比较广泛的一种数据结构,这里我写了二叉树的相关操作,包括初始化.新建.以及遍

数据结构(二十一)二叉树遍历算法的应用与二叉树的建立

一.顺序存储结构对树这种一对多的关系结构实现起来是比较困难的.但是二叉树是一种特殊的树,由于它的特殊性,使得用顺序存储结构也可以实现. 二.二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系,比如双亲与孩子的关系,左右兄弟的关系等. 三.完全二叉树可以将相应下标的结点存到数组的相应下标的位置上,对于一般的二叉树来说,完全可以将其按完全二叉树编号,只不过,把不存在的结点设置为"null"而已.这显然是对存储空间的浪费,所以

java数据结构之二叉树遍历的非递归实现

算法概述递归算法简洁明了.可读性好,但与非递归算法相比要消耗更多的时间和存储空间.为提高效率,我们可采用一种非递归的二叉树遍历算法.非递归的实现要借助栈来实现,因为堆栈的先进后出的结构和递归很相似.对于中序遍历来说,非递归的算法比递归算法的效率要高的多.其中序遍历算法的实现的过程如下:(1).初始化栈,根结点进栈:(2).若栈非空,则栈顶结点的左孩子结点相继进栈,直到null(到叶子结点时)退栈:访问栈顶结点(执行visit操作)并使栈顶结点的右孩子结点进栈成为栈顶结点.(3).重复执行(2),

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树 二叉树的创建,关系建立 二叉树的创建,关系建立2 三叉链表法 双亲链表: 二叉树的遍历 遍历的分析PPT 计算二叉树中叶子节点的数目:使用全局变量计数器 计算二叉树中叶子节点的数目:不使用全局变量计数器 无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟 求二叉树的高度 二叉树的拷