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

       
      

  • 相关阅读:
    使用RestTemplate进行服务调用的几种方式
    springmvc学习指南 之---第32篇 mybatis 嵌套的处理
    springmvc学习指南 之---第31篇 使用墨客进行测试报错
    springmvc学习指南 之---第30篇 异常的全局处理
    Effective Java 阅读笔记--之(一) 建造者模式(Builder)
    使用mybatis-generator.xml 生成PO 对象
    springmvc学习指南 之---第29篇 springmvc 返回json对象, 不想创建类的前提下
    springmvc学习指南 之---第28篇 springmvc的controller 如何解析视图view? 如何解析json,html,jsp?
    springmvc学习指南 之---第27篇 spring如何实现servlet3.0无web.xml 配置servlet对象的
    springmvc学习指南 之---第26篇 在idea中如何debug跟踪到tomcat内部代码
  • 原文地址:https://www.cnblogs.com/sango/p/12854269.html
Copyright © 2011-2022 走看看