【问题标题】:Deserializing a Binary Tree in Python with recursion使用递归在 Python 中反序列化二叉树
【发布时间】:2021-06-24 13:33:55
【问题描述】:

我正在尝试编写用于序列化和反序列化二叉树的代码。我成功地序列化了树,但是,我发现反序列化很困难。 (我知道有很多解决方案可用。但是,我更喜欢在查找之前先自学)

考虑下面的树

      __1
     /   \
    2     3
   / \     \
  4   5     6
     

我的序列化模块输出

[1, 2, 4, None, None, 5, None, None, 3, None, 6, None, None]

我的代码是

def serialize(root):
    nodes = list()
    stack = [root]
    while len(stack):
        node = stack.pop()
        if node is not None: 
            nodes.append(node.value)
            if node.right: 
                stack.append(node.right)
            else:
                nodes.append(None)
            if node.left: 
                stack.append(node.left)
            else:
                nodes.append(None)
                
    return nodes
  • 如何在不递归的情况下反序列化?
  • 是否有反序列化的递归版本?
  • 我做的树遍历,有名字吗?
  • 是否有递归版本的序列化?

也感谢任何指向有用材料的指针。

【问题讨论】:

  • 请只关注一个问题。你总是可以问一个新问题。你有什么尝试吗?你被困在哪里了?

标签: data-structures tree binary-tree binary-search-tree traversal


【解决方案1】:

你真的应该只问一个问题,所以我将只关注反序列化:

如何在不递归的情况下反序列化?

就像您用于序列化的非递归解决方案一样,您需要一个堆栈。您还需要知道当前值是用于左孩子还是右孩子。您可以从 preceding 输入值中知道这一点。它是None,这意味着下一个值总是为 right 孩子。如果不是,那么它总是意味着我们刚刚创建了一个父节点,并且当前值是关于它的 left 子节点。

此外,当您从根的虚拟父节点开始时,该算法会更容易一些,以便将树构建为其左侧子树:

def deserialize(data):
    stack = []
    prev_value = 1  # dummy value, can be anything, but not None
    parent = node = Node(prev_value)  # dummy node, whose left child will be the result
    for value in data:
        if value is None:
            if node.left is not None or prev_value is None:
                # Current None is about right child. Go up...
                node = stack.pop()
                while node.right is not None:
                    node = stack.pop()
        else:  # going down...
            stack.append(node)
            if prev_value is None:  # ...after going up
                node.right = Node(value)
                node = node.right
            else:
                node.left = Node(value)
                node = node.left
        prev_value = value
    return parent.left

是否有反序列化的递归版本?

是的,有,而且它需要更少的代码:

def deserialize(data):
    it = iter(data)

    def recur():
        value = next(it)
        return None if value is None else Node(value, recur(), recur())
    
    return recur()

上面的代码假定您有一个Node 构造函数,它接受(可选)其leftright 属性的参数:

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

我做的树遍历,有名字吗?

是的,它是preorder traversal

是否有递归版本的序列化?

是的,有。试一试。如果您在创建此类版本时遇到问题,请为此专门提出一个单独的问题。

【讨论】:

  • 谢谢,非常感谢您的帮助。我花了一些时间来理解你写的东西。不过,学习体验不错。我接近但永远无法完成它。我被困在你提到两个连续的“无”意味着下一个是正确的节点。
猜你喜欢
  • 1970-01-01
  • 2020-09-15
  • 2020-04-09
  • 2021-11-14
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2021-07-03
  • 2019-04-17
相关资源
最近更新 更多