二叉树是树(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...循环下去,直至没有节点可以访问为止。
来源:https://www.cnblogs.com/lch743/p/4492888.html