二叉树的遍历以及重建

二叉树(Binary Tree):一种树形结构,它的特点是每个节点至多只有两颗子树,即不存在度大于2的结点,
并且,二叉树的子树有左右之分,其次序不能任意颠倒。

二叉树结点的表示

首先创建一个节点类,每次实例化出对象时,作为父节点的存在,默认值为#,存在两个子节点为None:

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

二叉树的遍历

二叉树有四种遍历方式,前序,中序,后序和按层遍历。

二叉树简便示意图:

                           A

                        ↙  ↘

                      B         C

A为该节点的父节点也称为根节点,B是左子节点,C是右子节点。

其中前序的排列方式为根左右,把每三个关联的小节点综合一起看,都作为根左右的形式,如果是更多子节点的情况,看似略有复杂,但也依旧是以这种方式来看。

三层二叉树:

             A

         ↙  ↘

      B          C

   ↙ ↘     ↙ ↘

 D       E  F      G

前序:根左右。先把BDF,CFG看做是A的左右子节点,因此是从A开始读,A作为第一个,然后进到左子节点 BDE, 这时再把它看做一个小二叉树看待,其顺序为BDF,读完这个,以A为根的三个结构就读完了根左,然后剩下CFG,这时在读CFG。到此为止,这组二叉树的前序组合为ABDRCFG,这种读法从上往下,从根开始,把下面所有节点结构都以根左右的形式读取,遇到有子节点的情况变读左子节点,读完再读右。总结其格式:从根开始,找左,以左为根,找左,若无,找右,以右为根,找左,若无,找右,若无,找上一级右,以此类推。

中序:左根右。先把BDF,CFG看做是A的左右子节点,A1,A2。中序的读法为左根右,A1,A,A2。然后再看A1,D为左,B为中,E为右,D为叶节点(无子节点了),因此从D开始DBE,A1读完,然后为A,再看A2,A2为FCG,因此中序的顺序为:DBE>A>FCG。

后序:左右根A1,A2,A。A1在左右根:DEB,A2是FGC,A1,A2,A便是DEBFGCA。

按层遍历,就是按层来看,从上往下,从左往右,就是ABCDEFG。

# 前序遍历:以“根左右”顺序递归遍历
def preorder_traverse(node):
    if node is None:
        return None
    print(node.value)
    preorder_traverse(node.left)
    preorder_traverse(node.right)


# 中序遍历:以“左根右”顺序递归遍历
def inorder_traverse(node):
    if node is None:
        return None
    inorder_traverse(node.left)
    print(node.value)
    inorder_traverse(node.right)


# 后序遍历:以“左右根”顺序递归遍历
def postorder_traverse(node):
    if node is None:
        return None
    postorder_traverse(node.left)
    postorder_traverse(node.right)
    print(node.value)

那么如何根据前序和中序遍历结果重建(还原)二叉树呢?

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

举个栗子,例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

先作分析:

  • 根据前序遍历序列第一个元素1可知二叉树root结点值为1。
  • 使用1把中序遍历序列分成两部分,左侧 [4,7,2]一定是root.left所有值,右侧 [5,3,8,6]一定是root.right所有值。
  • [4,7,2]的前序遍历的顺序是前序序列第2-4个数值[2,4,7],所以在这棵子树2 是root结点数值。
  • 将2分开[4,7,2]为 [4,7]和[],发现 4,7两个数值都位于左结点,依次确定下一子树。。
  • 同理,root.right的[5,3,8,6]可以根据与[3,5,6,8]顺序关系依次确定整个二叉树。

总结一下:

  • 先获得root结点的值,根据值的位置把中序遍历序列分为两部分
  • 根据两部分序列长度将除root值外的前序序列同样分为两部分
  • 数组两两组合通过递归找到子孙树左右节点以及值
  • 注意将序列分割的起点以及终点

 来看看详细代码:


# class TreeNode:

#     def __init__(self, x):

#         self.val = x

#         self.left = None

#         self.right = None

class Solution:

    # 返回构造的TreeNode根节点

    def reConstructBinaryTree(self, pre, tin):

        if len(pre)==0 or len(tin)==0:

            return None

        root = TreeNode(pre[0])   #将根定义成节点的形式

        i=tin.index(pre[0])   #寻找位置将左右子树分开

        root.left = self.reConstructBinaryTree(pre[1:1+i],tin[:i])

        root.right = self.reConstructBinaryTree(pre[1+i:],tin[i+1:])

        return root

 

转载于:https://my.oschina.net/magicalee/blog/1924696

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值