数据结构与算法-构建二叉树

构建二叉树

已知前序遍历与中序遍历或已知后序遍历和中序遍历可以构建唯一的二叉树

根据前序遍历与中序遍历建树

class Tree_Node():
    def __init__(self,val):
        self.val = val
        self.left = None
        self.right = None
# 构建二叉树
# 根据前序遍历与中序遍历构建二叉树
# 前序遍历[3,9,2,1,7]
# 中序遍历[9,3,1,2,7]
# 后序遍历[9,1,7,2,3]
# 根据前序遍历,确定树的构建顺序
# 根据中序遍历,确定子节点的数量关系
# 前序遍历中,第一层树节点为{根:3},{左子树:9},{右子树:2,1,7}
# 第二层节点为:{叶节点:2}{左:1}{右:7}
# 利用中序遍历来表示:前序遍历中单签节点及叶子结点的索引范围
# 前序遍历中:根节点:i=0,在中序遍历中索引范围为{l:0,r:len(nums)}
# 前序遍历中:左子树:i+1,在中序遍历中的索引范围为:{l,m-1:中序遍历中根节点左侧数值}
# 前序遍历中:右子树:i+1+(m-l:剩余左子树的数量),在中序遍历中的索引范围为:{m+1中序遍历中根节点右侧数值,r}
# 利用递归,逐步更新左右子树的索引范围,即可实现利用前序便利与中序遍历数组构建唯一二叉树

def dfs1(preorder,inorder,i,l,r):
        # print("当前高度的根节点所在右子树中的索引{}".format(i))
        # print("当前左右边界l:{} and r:{}".format(l,r))
        if r-l < 0 or i >r:
            return None
        # 初始化根节点
        root = Tree_Node(preorder[i])
        #中序遍历中根节点的索引
        m = inorder[preorder[i]]
        #左子树
        root.left = dfs1(preorder,inorder,i+1,l,m-1)
        # 右子树
        root.right = dfs1(preorder,inorder,i+1+(m-l),m+1,r)
        return root
def build_tree_basepre(preorder,inorder):
    inorder = {value:key for key,value in enumerate(inorder)}
    l = 0
    r = len(preorder)-1
    i = 0
    root = dfs1(preorder,inorder,i,l,r)
    return root

preorder = [3,9,2,1,7]
inorder = [9,3,1,2,7]
pre_tree = build_tree_basepre(preorder,inorder)
print(pre_tree.right.right.val)

根据后序遍历与中序遍历建树

# 中序遍历[9,3,1,2,7]
# 后序遍历[9,1,7,2,3]
# 根据前序遍历,确定树的构建顺序
# 根据中序遍历,确定子节点的数量关系
# 前序遍历中,第一层树节点为{根:3},{左子树:9},{右子树:1,7,2}
# 第二层节点为:{叶节点:2}{左:1}{右:7}
# 利用中序遍历来表示:前序遍历中单签节点及叶子结点的索引范围
# 后序遍历中:根节点:i=r,在中序遍历中索引范围为{l:0,r:len(nums)}
# 后遍历中:右子树:i=i-1,在中序遍历中的索引范围为:{l,m-1:中序遍历中根节点左侧数值}
# 后遍历中:左子树:i = i-1-(m-1-l):剩余左子树的数量),在中序遍历中的索引范围为:{m+1中序遍历中根节点右子树,r}
# 利用递归,逐步更新左右子树的索引范围,即可实现利用前序便利与中序遍历数组构建唯一二叉树
def dfs2(postorder,inorder,i,l,r):
    # 初始化根节点

    if r-l <0 or i < 0 :
       return None
    print("当前高度的根节点所在右子树中的索引{}".format(i))
    print("当前左右边界l:{} and r:{}".format(l,r))
    root = Tree_Node(postorder[i])
    #中序遍历中根节点的索引
    m = inorder[postorder[i]]
    #左子树
    # print("创建左子树")
    root.left = dfs2(postorder,inorder,i-1-(m-l-1),l = l,r = m-1)
    # 右子树,i为初始化右子的根节点
    # print("创建右子树")
    root.right = dfs2(postorder,inorder,i-1,m+1,r)
    return root 
def build_tree_baseafter(afterorder,inorder):
    inorder = {value:key for key,value in enumerate(inorder)}
    l = 0
    r = len(afterorder)-1
    i = r
    root = dfs2(afterorder,inorder,i,l,r)
    return root
postorder = [9,1,7,2,3]
inorder = [9,3,1,2,7]

post_tree = build_tree_baseafter(postorder,inorder)
print(post_tree.right.right.val)

总结

  • 前序遍历中节点之间的关系为根节点->左子树->右子树,根据这个顺序将根节点为i,左子树为:i+1,右子树为i+1+(左子树的数量);根据中序遍历,确定i的取值范围(中序遍历的特点是左子树->根节点->右子树,可以区分左子树与右子树存包含的子节点数量关系),首先确定中序遍历中的根节点所在索引m进而可以划分左子树与右子树之间的索引区间左子树:[l:m-1];右子树:[m+1,r];利用递归实现二叉树的构建。
    值得注意的一点是,二叉树构建子树的递归条件(边界条件为,r-l>0,即数组区间不能小于0,其中当i>r)
  • 利用后序遍历与中序遍历构建二叉树则是利用后序遍历数组:左子树->右子树->根节点;则利用根节点为i=r,右子树i = i-1,左子树:i-1-(剩余左子树节点个数:m-1-l)
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SatVision-RS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值