剑指Offer 04 - 重建二叉树详解(Python版)

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

什么是二叉树?

二叉树(Binary Tree)是n(n≥0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。二叉树与普通有序树不同,二叉树严格区分左孩子和右孩子,即使只有一个子节点也要区分左右。

二叉树的遍历

遍历 :沿某条搜索路径周游二叉树,对树中的每一个节点访问一次且仅访问一次。
遇到没遍历的新节点都当根处理

先序遍历: 先访问树根,再访问左子树,最后访问右子树;根左右
中序遍历: 先访问左子树,再访问树根,最后访问右子树;左根右
后序遍历: 先访问左子树,再访问右子树,最后访问树根;左右根
层次遍历: 从根节点开始,逐层从左向右进行遍历。
在这里插入图片描述

使用Python实现二叉树

# 二叉树节点
class TreeNode:
  def __init__(self, val=None, left=None, right=None):
    self.val = val
    self.left = left
    self.right = right

#  二叉树操作
class Bitree:
  def __init__(self, root=None):
    self.root = root  # 获取树根

  # 先序遍历
  def preOrder(self,node):
    # 传入根节点
    if node is None:
      return
	# 打印根节点数据
    print(node.val,end=' ')
    # 将根节点的左点节 作为根节点 递归调用自身,直至满足node is None,停止递归
    self.preOrder(node.left)
    self.preOrder(node.right)

  #  中序遍历
  def inOrder(self, node):
    if node is None:
      return
    self.inOrder(node.left)
    print(node.val, end=' ')
    self.inOrder(node.right)

  #  后序遍历
  def postOrder(self, node):
    if node is None:
      return
    self.postOrder(node.left)
    self.postOrder(node.right)
    print(node.val, end=' ')
    
if __name__ == "__main__":
  #  后序遍历 BFGDIHECA
  # 构建树 
  b = TreeNode('B')
  f = TreeNode('F')
  g = TreeNode('G')
  d = TreeNode('D', f, g)
  i = TreeNode('I')
  h = TreeNode('H')
  e = TreeNode('E', i, h)
  c = TreeNode('C', d, e)
  a = TreeNode('A', b, c)  # 树根

  #  初始化树对象,得到树根
  bt = Bitree(a)
  # 先序
  bt.preOrder(bt.root)
  print()
  #  中序
  bt.inOrder(bt.root)
  print()
  #  后序
  bt.postOrder(bt.root)
  print()

根据题目构建二叉树图

在这里插入图片描述

构建代码

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre: list, tin: list) -> object:
        """
        pre: 前序列表
        tin: 中序列表
        """
        # write code here
        if len(pre) == 0:
            return None
        if len(pre) == 1:
            return TreeNode(pre[0])
        else:
            root = TreeNode(pre[0])  # 前序序列的第一个肯定是当前子树的根节点
            rootid = tin.index(root.val)  # 通过根节点在中序序列中的位置划分出左右子树包含的节点
            root.left = self.reConstructBinaryTree(pre[1:rootid + 1], tin[:rootid])
            root.right = self.reConstructBinaryTree(pre[rootid + 1:], tin[rootid + 1:])
        return root

代码流程

在这里插入图片描述

对结果进行验证

完整代码

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre: list, tin: list) -> object:
        """
        pre: 前序列表
        tin: 中序列表
        """
        # write code here
        if len(pre) == 0:
            return None
        if len(pre) == 1:
            return TreeNode(pre[0])
        else:
            root = TreeNode(pre[0])  # 前序序列的第一个肯定是当前子树的根节点
            rootid = tin.index(root.val)  # 通过根节点在中序序列中的位置划分出左右子树包含的节点
            root.left = self.reConstructBinaryTree(pre[1:rootid + 1], tin[:rootid])
            root.right = self.reConstructBinaryTree(pre[rootid + 1:], tin[rootid + 1:])
        return root

class Bitree:
    def __init__(self, root=None):
        self.root = root  # 获取树根

    #  先序遍历
    def preOrder(self, node):
        # 传入根节点
        if node is None:
            return
        # 打印根节点数据
        print(node.val, end=' ')
        # 将根节点的做点节 作为根节点 调用自身
        self.preOrder(node.left)
        self.preOrder(node.right)

    #  中序遍历
    def inOrder(self, node):
        if node is None:
            return
        self.inOrder(node.left)
        print(node.val, end=' ')
        self.inOrder(node.right)

    #  后序遍历
    def postOrder(self, node):
        if node is None:
            return
        self.postOrder(node.left)
        self.postOrder(node.right)
        print(node.val, end=' ')

if __name__ == '__main__':
    s = Solution()
    pre = [1, 2, 4, 7, 3, 5, 6, 8]
    tin = [4, 7, 2, 1, 5, 3, 8, 6]

    root = s.reConstructBinaryTree(pre, tin)

    #  初始化树对象,得到树根
    bt = Bitree(root)
    #  先序
    bt.preOrder(bt.root) # 1 2 4 7 3 5 6 8 
    print()
    #  中序
    bt.inOrder(bt.root) # 4 7 2 1 5 3 8 6 
    print()
    #   后序
    bt.postOrder(bt.root) # 7 4 2 5 8 6 3 1 
    print()

补充 代码实现二叉树层次遍历

'''
利用队列先进先出特性,实现二叉树层次遍历
'''
#  自定义队列异常
class QueueError(Exception):
  pass

# 队列操作类
class SQueue:
  def __init__(self):
    self._elems = []

  # 判断队列空
  def is_empty(self):
    return self._elems == []

  # 入队 从列表尾部
  def enqueue(self, elem):
    self._elems.append(elem)

  # 出队 从列表开头
  def dequeue(self):
    if not self._elems:
      raise QueueError("Queue is empty")
    return self._elems.pop(0)

# 二叉树节点
class TreeNode:
  def __init__(self, val=None, left=None, right=None):
    self.val = val
    self.left = left
    self.right = right
    
class Bitree:
    def __init__(self, root=None):
        self.root = root  # 获取树根
        
  	# 层次遍历
  	def levelOrder(self,node):
    	sq = SQueue()
    	sq.enqueue(node) # 从node遍历
    	while not sq.is_empty():
      	node = sq.dequeue() # 出队一个
      	print(node.val,end=' ') # 遍历数据
      	if node.left:
        	sq.enqueue(node.left)
      	if node.right:
        	sq.enqueue(node.right)

如有错误,欢迎指正

发布了15 篇原创文章 · 获赞 17 · 访问量 1263
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章