【问题标题】:Adjust construct() function调整construct()函数
【发布时间】:2021-07-07 18:26:07
【问题描述】:
class Node:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right
 
def construct(start, end, preorder, pIndex, dict):
 
    # base case
    if start > end:
        return None, pIndex
 
    root = Node(preorder[pIndex])
    pIndex = pIndex + 1
 
    index = dict[root.data]
 
    root.left, pIndex = construct(start, index - 1, preorder, pIndex, dict)
 
    root.right, pIndex = construct(index + 1, end, preorder, pIndex, dict)
 
    return root, pIndex     

def constructTree(inorder, preorder):
 
    dict = {}
    for i, e in enumerate(inorder):
        dict[e] = i
 
    pIndex = 0
 
    return construct(0, len(inorder) - 1, preorder, pIndex, dict)[0]
 
 
if __name__ == '__main__':
 
 
    inorder = [4, 2, 1, 7, 5, 8, 3, 6]
    preorder = [1, 2, 4, 3, 5, 7, 8, 6]
 
    root = constructTree(inorder, preorder)
 
    print("The inorder traversal is ", end='')
    inorderTraversal(root)
 
    preorderTraversal(root)

此代码使用前序和中序遍历构造一棵树。如何修改该代码以使其适用于 inorder-postorder 和 preorder-postorder?我想我只需要修改construct() 并以类似的方式创建constructPreOrderInOrderTree()constructPreOrderPostOrderTree()

编辑

假设我有inorder=[3, 7, 1, 10, 9, 5, 8, 6, 4, 2]postorder = [3, 7, 10, 9, 1, 8, 4, 6, 2, 5]construct() 会针对 inorder-preorder 执行此操作,但不适用于该示例。所以我需要该函数的一个版本,它可以同时用于 inorder-postorder 和 preorder-postorder。

【问题讨论】:

  • 你能解释一下inorder-preorderpreorder-postorderinorder-postorder是什么意思吗?我可以理解仅订购或预购或后订购的含义,但不能合并。
  • 哦,是的!如果我给你inorder=[3, 7, 1, 10, 9, 5, 8, 6, 4, 2],你就不能完全重建二叉树。您需要其他东西来完全构建二叉树。 inorder = [4, 2, 1, 7, 5, 8, 3, 6]preorder = [1, 2, 4, 3, 5, 7, 8, 6] 将从该问题生成二叉树:stackoverflow.com/questions/67059333/…
  • @Arty 如果您想了解更多,请查看geeksforgeeks.org/…
  • 但是 GeeksForGeeks 网站上已经提供了算法代码。 StackOverflow 专家不需要发明一些东西,只需从那里获取代码。例如这里是inorder-postorder 算法。我认为他们的网站上也可以使用 preorder-postorder。
  • 顺便说一句,您确定任务的preorder-postorder 变体是可解决的吗?这个任务是你自己发明的,还是 geeksforgeeks 练习题数据集的一部分?您能否在 GeeksForGeeks 网站上指向preorder-postorder 问题描述的链接?

标签: python binary-tree inorder preorder postorder


【解决方案1】:

甚至没有阅读 Geeks-for-Geeks 页面,我决定实现自己的构造函数算法(preorder-postorder、preorder-inorder、inorder-postorder)。

我所有的算法都是O(N^2) 复杂度。

除了构造函数(construct_preorder_postorder()construct_preorder_inorder()construct_inorder_postorder())我还实现了遍历函数(traverse_preorder()traverse_inorder()traverse_postorder())、控制台树打印函数(print_tree())和节点相等比较函数(__eq__())。

Try it online!

class Node:
    def __init__(self, data, left = None, right = None):
        self.data = data
        self.left = left
        self.right = right
    def __eq__(self, other):
        return (self.data == other.data and self.left == other.left and
            self.right == other.right)
        
def traverse_inorder(node):
    return ([] if node is None else
        traverse_inorder(node.left) + [node.data] + traverse_inorder(node.right))
        
def traverse_preorder(node):
    return ([] if node is None else
        [node.data] + traverse_preorder(node.left) + traverse_preorder(node.right))
        
def traverse_postorder(node):
    return ([] if node is None else
        traverse_postorder(node.left) + traverse_postorder(node.right) + [node.data])
        
def construct_preorder_postorder(pre, post):
    assert sorted(pre) == sorted(post) and len(pre) == len(set(pre)), (pre, post)
    if len(pre) == 0:
        return None
    if len(pre) == 1:
        return Node(pre[0])
    root, l = pre[0], pre[1]
    for i, e in enumerate(post):
        if e == l:
            ls = i + 1
            rs = len(post) - 1 - ls
            break
    return Node(root,
        None if ls == 0 else construct_preorder_postorder(pre[1:1 + ls], post[:ls]),
        None if rs == 0 else construct_preorder_postorder(pre[-rs:], post[-1 - rs:-1]))
        
def construct_preorder_inorder(pre, ino):
    assert sorted(pre) == sorted(ino) and len(pre) == len(set(pre)), (pre, ino)
    if len(pre) == 0:
        return None
    if len(pre) == 1:
        return Node(pre[0])
    root, l = pre[0], pre[1]
    for i, e in enumerate(ino):
        if e == root:
            ls = i
            rs = len(ino) - 1 - ls
            break
    return Node(root,
        None if ls == 0 else construct_preorder_inorder(pre[1:1 + ls], ino[:ls]),
        None if rs == 0 else construct_preorder_inorder(pre[-rs:], ino[-rs:]))
        
def construct_inorder_postorder(ino, post):
    assert sorted(ino) == sorted(post) and len(ino) == len(set(ino)), (ino, post)
    if len(post) == 0:
        return None
    if len(post) == 1:
        return Node(post[0])
    root, r = post[-1], post[-2]
    for i, e in enumerate(ino):
        if e == root:
            ls = i
            rs = len(ino) - 1 - ls
            break
    return Node(root,
        None if ls == 0 else construct_inorder_postorder(ino[:ls], post[:ls]),
        None if rs == 0 else construct_inorder_postorder(ino[-rs:], post[-1 - rs:-1]))
    
def print_tree(node):
    def inner(node, *, upref = '', cpref = '', dpref = ''):
        if node is None:
            return
        inner(node.right, upref = dpref + '  |',
            cpref = dpref + '  /', dpref = dpref + '   ')
        print(cpref + '--' + str(node.data))
        inner(node.left, upref = upref + '   ',
            cpref = upref + '  \\', dpref = upref + '  |')
    inner(node)
        
if __name__ == '__main__':
    node = Node(1, Node(2, Node(4)), Node(3, Node(5, Node(7), Node(8)), Node(6)))
    print_tree(node)
    preorder, inorder, postorder = (
        traverse_preorder(node), traverse_inorder(node), traverse_postorder(node))
    preorder_cons, inorder_cons, postorder_cons = (
        construct_preorder_postorder(preorder, postorder),
        construct_preorder_inorder(preorder, inorder),
        construct_inorder_postorder(inorder, postorder),
    )
    assert preorder_cons == inorder_cons == postorder_cons

输出:

     /--6
  /--3
  |  |  /--8
  |  \--5
  |     \--7
--1
  \--2
     \--4

【讨论】:

    【解决方案2】:

    变化:

    • 使用像lookup 这样的变量名以避免掩盖现有类型名称(例如dict
    • 从右到左
      • 从头开始
      • 沿途递减 pIndex
      • 从相反方向更新 pIndex
    def construct_post(start, end, postorder, pIndex, lookup):
        # base case
        if start > end or pIndex < 0:
            return None, pIndex
     
        root = Node(postorder[pIndex])
        
        # go from the right to the left instead
        pIndex = pIndex - 1
    
        index = lookup[root.data]
    
        # update pIndex going in the opposite direction
        root.right, pIndex = construct_post(index + 1, end, postorder, pIndex, lookup)
        root.left, pIndex = construct_post(start, index - 1, postorder, pIndex, lookup)
    
        return root, pIndex
    
    
    def constructTree_post(inorder, postorder):
        lookup = {e: i for i, e in enumerate(inorder)}
        pIndex = len(postorder) - 1
    
        # start from the end
        return construct_post(0, len(inorder) - 1, postorder, pIndex, lookup)[0]
    
    

    生成的树:

              1
           /     \
         2        3
       /        /   \
      4        5     6
              / \
             7   8
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      相关资源
      最近更新 更多