zoukankan      html  css  js  c++  java
  • 二叉树的遍历——递归非递归实现

    一、简介 


       二叉树的三种遍历方式我相信大家都了然于心,前序遍历、中序遍历、后序遍历。对于这三种遍历的递归实现,我们都不容易忘记。不过,对于非递归实现,我相信会有很多人会跟我一样,背了忘,再背再忘......(很多算法题都是这样,比如各种排序算法的实现)。经过认真观察思考后,发现实现起来是那么的简单,只要记住三者遍历顺序就够了。前序遍历,先访问父节点(中)、然后左子树(左)、最后右子树(右);中序遍历:左、中、右;后序遍历:左、右、中。如果还不明白这三种遍历方式的访问顺序,建议去看看动画的教程。

    二、递归实现


      递归实现结构很好记,上来写两递归,递归左子树,递归右子树。前序遍历,访问节点(打印节点)在两个递归前面——中、左、右;中序遍历,访问放递归中间——左中右;后序遍历,先两递归,最后才访问——左、中、右。

     1 # Definition for a binary tree node.
     2 # class TreeNode:
     3 #     def __init__(self, x):
     4 #         self.val = x
     5 #         self.left = None
     6 #         self.right = None
     7 
     8 
     9 def preorder_with_recursion(root):          
    10         if root is None:
    11             return
    12       
    13         print(root.val)
    14         preorder_with_recursion(root.left)
    15         preorder_with_recursion(root.right) 
    16 
    17 
    18 def inorder_with_recursion( root):
    19         if root is None:
    20             return 
    21 
    22         inorder_with_recursion(root.left)
    23         print(root.val)
    24         inorder_with_recursion(root.right)
    25 
    26 
    27 def postorder_with_recursion(root):
    28         if root is None:
    29             return 
    30 
    31         postorder_with_recursion(root.left)
    32         postorder_with_recursion(root.right)
    33         print(root.val)
    34               

    三、非递归实现


      非递归不外乎就是我们自己维护一个栈结构,来控制出栈、进栈的时机。对于前序遍历(中、左、右),因为先打印父节点 , 因此我们每循环一次,就可以出栈打印,并且将右孩子和左孩子压入栈中;中序遍历(左、中、右),先打印最左子树,我们可以不断地将左节点压入栈中,直到左子节点为空,出栈打印,并判断有孩子是否存在。如果存在则压入栈并重复查找最左子过程, 如果不存在右孩子,则继续出栈打印。后序遍历(左、右、中),访问左子树跟中序遍历的方式相同,唯一区别的是,因为得先打印右子树,因此把这节点继续存入栈(并处理为已访问),让右子树先进栈出栈,最后才轮到该节点打印。

     1 def preorder_with_loop(root):
     2     if root is None:
     3         return
     4 
     5     stack = []
     6     stack.append(root)
     7     while stack:
     8         cur = stack.pop()
     9         print(cur.val)
    10         if cur.right:
    11             stack.append(cur.right)
    12         if cur.left:
    13             stack.append(cur.left)
    14 
    15 
    16 def inorder_for_loop(root):
    17     if root is None:
    18         return
    19 
    20     stack = []
    21     cur = root
    22     while cur or stack:
    23         if cur:
    24             stack.append(cur)
    25             cur = cur.left
    26         else:
    27             cur = stack.pop()
    28             print(cur.val)
    29             cur = cur.right
    30 
    31 
    32 def postorder_with_loop(root): 
    33     if root is None:
    34         return
    35 
    36     stack = []
    37     cur = root
    38     while cur or stack:
    39         if cur:
    40             stack.append(cur)
    41             cur = cur.left
    42         else:
    43             cur = stack.pop()
    44             # 先判断有没有右子树,如果没有直接打印,如果有,继续入栈,等右子树先出栈打印。
    45             if cur.right:
    46                 right = cur.right
    47                 """
    48                 第二次入栈,右子树也随后入栈,因此将右子树设置为None来控制
    49                 下次出栈时到可以打印,而不是再次访问右子树进入死循环。
    50                 """
    51                 cur.right = None
    52                 stack.append(cur)
    53                 cur = right
    54             else:
    55                 print(cur.val)
    56                 cur = None

       
      

  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/sango/p/12854269.html
Copyright © 2011-2022 走看看