二叉树多种遍历

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明,违反必究。
本文链接:https://blog.csdn.net/junxing2018_wu/article/details/116713857

遍历通常分为**前序遍历中序遍历后序遍历层序遍历**四种方式。
需要提一句的是,遍历方式只是打印顺序而已,四种遍历复杂度是相同。

  • 前序遍历:根 - 左 - 右
  • 中序遍历:左 - 根 - 右
  • 后序遍历:左 - 右 - 根
  • 层序遍历:根节点 - 第1层 - 第2层 - … 最后一层

非递归遍历(辅助栈)

由于每个节点都要进栈和出栈,所以时间复杂度O(N),同样空间复杂度也为O(N),N为结点数。

  • 前序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, x):
      #         self.val = x
      #         self.left = None
      #         self.right = None
      
      class Solution:
          def preorderTraversal(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              pre = None
              res = []
              stack = [root]
              while stack:
                  temp = stack.pop()
                  res.append(temp.val)
                  # 因为栈先进后出,因此子节点压入的顺序是先右后左。
                  if temp.right:
                      stack.append(temp.right)
                  if temp.left:
                      stack.append(temp.left)
              return res
            
          def preorderTraversal_0(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  result = [root.val]
                  stack = [root.right, root.left]
                  while len(stack)>0:
                      node = stack.pop()
                      if node is not None:
                          result.append(node.val)
                          stack.extend([node.right, node.left])
                  return result
      
          def preorderTraversal_1(self, root: TreeNode) -> List[int]:
              node = root
              stack = []        
              ret = []
              while (node or stack):        # 树不空,或者堆栈不空
                  while node:               # 只要节点不是 None,即树不空,就一直把节点压入堆栈,并且一直往左走到死胡同里,结束循环
                      stack.append(node)    # 入栈(第一次碰到)
                      ret.append(node.val)  # 前序遍历是第一次碰到就输出
                      node = node.left      # 一直往左走,并一直压入堆栈
                  # 上述压栈循环结束,跳出
                  if stack:                         
                      node = stack.pop()    # 出栈(第二次碰到,中序遍历就是放在这里之后),开始往回走,pop出 node
                      node = node.right     # 继续往右走
              return ret
      
    
  • 后序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, x):
      #         self.val = x
      #         self.left = None
      #         self.right = None
      
      class Solution:
          def postorderTraversal(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              pre = None
              ret = []
              stack = [root]
              while stack:
                  temp = stack[-1]  # 这里不能直接用pop,因为只有读取该节点的时候才要已经读取了的节点pop出栈
                  if (temp.left == None and temp.right == None) or (pre and (pre == temp.left or pre == temp.right)):
                    # 用pre来进行标志,由于是后序遍历,
                    # 如果当前节点是叶节点(左右子节点为空),读取值,
                    # 如果不是叶节点但是pre是他的子节点,
                    # 就说明这个节点也是当前应该读取的点
                      ret.append(temp.val)
                      pre = temp
                      stack.pop()
                  else:  # 因为栈先进后出,因此子节点压入的顺序是先右后左。
                      if temp.right:
                          stack.append(temp.right)
                      if temp.left:
                          stack.append(temp.left)
              return ret
      
          def postorderTraversal_0(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  result = []
                  stack = [root.val, root.right, root.left]
                  while len(stack)>0:
                      node = stack.pop()
                      if isinstance(node, TreeNode):
                          stack.extend([node.val, node.right, node.left])
                      elif isinstance(node, int):
                          result.append(node)
                  return result
              
          def postorderTraversal_1(self, root: TreeNode) -> List[int]:
              node = root
              stack = []
              ret = []
              while (node or stack):
                  while node:
                      stack.append(node)
                      ret.append(node.val)
                      node = node.right               # 先 right,再 left
                  if stack:
                      node = stack.pop()
                      node = node.left
              return ret[::-1]             # 最后逆序输出
      
          def postorderTraversal_2(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              ret = []
              stack = []
              stack.append(root)
              while len(stack) > 0:
                  node = stack.pop()
                  left = node.left
                  right = node.right
                  ret.append(node.val)
                  if left is not None:
                      stack.append(left)
                  if right is not None:
                      stack.append(right)
              return ret[::-1]
    
  • 中序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, val=0, left=None, right=None):
      #         self.val = val
      #         self.left = left
      #         self.right = right
      class Solution:
          def inorderTraversal(self, root: TreeNode) -> List[int]:
              """ 中序遍历 迭代 
         		  1. 遇到一个节点,将其压入堆栈,并去遍历它的左子树
              2. 当左子树遍历结束后,从栈顶弹出这个节点并访问它
              3. 然后按照其右指针再去中序遍历该节点的右子树
              """
              node = root
              stack = []
              ret = []
              while (node or stack):
                  while node:
                      stack.append(node)       # 第一次碰到
                      node = node.left
                  if stack:
                      node = stack.pop()      # pop 出 node,即第二次碰到
                      ret.append(node.val) # 第二次碰到之后输出
                      node = node.right
              return ret
      
          def inorderTraversal_0(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  result = []
                  stack = [root.right, root.val, root.left]
                  while len(stack)>0:
                      node = stack.pop()
                      if isinstance(node, TreeNode):
                          stack.extend([node.right, node.val, node.left])
                      elif isinstance(node, int):
                          result.append(node)
                  return result
      
    
  • 层序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, val=0, left=None, right=None):
      #         self.val = val
      #         self.left = left
      #         self.right = right
      class Solution:
          def levelOrder(self, root: TreeNode) -> List[List[int]]:
              def children(root: TreeNode):
                  return [n for n in [root.left, root.right] if n is not None]
      
              if root is None:
                  return []
              else:
                  result = []
                  node_list = [root]
                  while len(node_list) > 0:
                      result.append([n.val for n in node_list])
                      tmp_stack = []
                      for n in node_list:
                          tmp_stack += children(n)
                      node_list = tmp_stack
                  return result
      
    

递归遍历

递归实现的本质也是系统帮我们建立了栈结构,而系统栈需要记住每个节点的值,所以空间复杂度仍为O(N)

时间复杂度根据master公式求得。

公式 T(N) = a*T(N/b) + O (N^d)
代入公式得:T(N)=2*T(N/2)+O(1),即 a = 2, b = 2, d = 0
得到 log(2,2) = 1 > 0,
代入公式得:O(N^log(b,a)) = O(N^log(2,2)) = O(N)

所以递归遍历的时间复杂度为O(N)

  • 前序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, val=0, left=None, right=None):
      #         self.val = val
      #         self.left = left
      #         self.right = right
      class Solution:
          def preorderTraversal(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  return (
                      [root.val]
                      + self.preorderTraversal(root.left)
                      + self.preorderTraversal(root.right)
                  )
    
  • 后序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, x):
      #         self.val = x
      #         self.left = None
      #         self.right = None
      
      class Solution:
          def postorderTraversal(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  return (
                      self.postorderTraversal(root.left)
                      + self.postorderTraversal(root.right)
                      + [root.val]
                  )
    
  • 中序遍历

      # Definition for a binary tree node.
      # class TreeNode:
      #     def __init__(self, val=0, left=None, right=None):
      #         self.val = val
      #         self.left = left
      #         self.right = right
      class Solution:
          def inorderTraversal(self, root: TreeNode) -> List[int]:
              if root is None:
                  return []
              else:
                  return (
                      self.inorderTraversal(root.left)
                      + [root.val]
                      + self.inorderTraversal(root.right)
                  )
    

莫里斯(Morris)遍历

时间复杂度O(N)空间复杂度O(1),N为结点数。

Morris遍历的实现原则

0 记作当前节点为cur。
1 如果cur无左孩子,cur向右移动(cur=cur.right)
2 如果cur有左孩子,找到cur左子树上最右的节点,记为mostright
  a. 如果mostright的right指针指向空,让其指向cur,cur向左移动(cur=cur.left)
  b. 如果mostright的right指针指向cur,让其指向空,cur向右移动(cur=cur.right)
3 cur为空时,停止遍历实现以上的原则,即实现了morris遍历。
  • 前序遍历

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, val=0, left=None, right=None):
    #         self.val = val
    #         self.left = left
    #         self.right = right
    class Solution:
        def preorderTraversal(self, root: TreeNode) -> List[int]:
            if root is None:
                return []
            else:
                cur = root
                ret = []
                mostRight = None
                while cur is not None:
                    # cur表示当前节点,mostRight表示cur的左孩子的最右节点
                    mostRight = cur.left
                    if mostRight is not None:
                        # cur有左孩子,找到cur左子树最右节点
                        while mostRight.right is not None and mostRight.right != cur:
                            mostRight = mostRight.right
                        # mostRight的右孩子指向空,让其指向cur,cur向左移动
                        if mostRight.right is None:
                            mostRight.right = cur
                            ret.append(cur.val)
                            cur = cur.left
                            continue
                        else:
                            # mostRight的右孩子指向cur,让其指向空,cur向右移动
                            mostRight.right = None
                    else:
                        ret.append(cur.val)
                    cur = cur.right
            return ret
    
  • 中序遍历

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, val=0, left=None, right=None):
    #         self.val = val
    #         self.left = left
    #         self.right = right
    class Solution:
        def inorderTraversal(self, root: TreeNode) -> List[int]:
            if root is None:
                return []
            else:
                cur = root
                ret = []
                mostRight = None
                while cur is not None:
                    # cur表示当前节点,mostRight表示cur的左孩子的最右节点
                    mostRight = cur.left
                    if mostRight is not None:
                        # cur有左孩子,找到cur左子树最右节点
                        while mostRight.right is not None and mostRight.right != cur:
                            mostRight = mostRight.right
                        # mostRight的右孩子指向空,让其指向cur,cur向左移动
                        if mostRight.right is None:
                            mostRight.right = cur
                            cur = cur.left
                            continue
                        else:
                            # mostRight的右孩子指向cur,让其指向空,cur向右移动
                            mostRight.right = None
                    ret.append(cur.val)
                    cur = cur.right
            return ret
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值