在Python中错误实现BST反序列化
这是我用Python实现的BST在Python中错误实现BST反序列化,python,binary-search-tree,Python,Binary Search Tree,这是我用Python实现的BST class BST: def __init__(self): self.root = None self.size = 0 def insert(self, item): self.root = self.insert_helper(item, self.root) self.size += 1 return self.root def insert_he
class BST:
def __init__(self):
self.root = None
self.size = 0
def insert(self, item):
self.root = self.insert_helper(item, self.root)
self.size += 1
return self.root
def insert_helper(self, item, root):
if root is None:
p = Node(item)
root = p
return root
if item > root.data:
root.right = self.insert_helper(item, root.right)
else:
root.left = self.insert_helper(item, root.left)
return root
class Node:
def __init__(self, data):
if data is None:
raise ValueError('Cannot create Node with None value.')
self.data = data
self.left = None
self.right = None
现在,我正在尝试将BST序列化
和反序列化成一个列表,反之亦然
这是序列化代码
def serialize(root):
tree_list = []
serialize_helper(root, tree_list)
return tree_list
def serialize_helper(root, tree_list):
if root is None:
tree_list.append(sys.maxsize)
return
tree_list.append(root.data)
serialize_helper(root.left, tree_list)
serialize_helper(root.right, tree_list)
这是反序列化的代码
def deserialize(tree_list):
index = 0
return deserialize_helper(tree_list, index)
def deserialize_helper(tree_list, index):
if index == len(tree_list) or tree_list[index] == sys.maxsize:
return None
root = Node(tree_list[index])
index += 1
root.left = deserialize_helper(tree_list, index)
root.right = deserialize_helper(tree_list, index)
return root
这段代码有缺陷,在左侧和右侧都复制了一个子节点。我调试了代码,似乎当递归折叠时,索引减少了,因此我得到了这种行为。有人能帮我吗 在Python中有两大类对象:不可变对象和可变对象。必须了解它们之间的区别:
a = [] # a list, lists are mutable
b = a # b and a now reference the same object
b.append(1) # change b and the change will be in-place
print(a) # since a references the same object
# [1]
a = 1 # an int, ints are immutable
b = a # b and a may well reference the same object, but
b += 1 # since the object cannot change a new object is bound to b
print(a) # leaving a unaffected
# 1
类似地,如果您将列表传递给一个函数,而该函数更改了列表,但没有显式返回列表,那么调用方仍然可以看到这些更改,事实上,持有列表引用的任何人都可以看到这些更改。有些人把这称为副作用。您正在序列化服务器中使用此技术
如果将一个不可变对象(如索引
)传递给一个函数,并在该函数中对其进行操作,则原始对象不会更改。函数中的名称仅绑定到调用方不可见的新对象,除非显式返回它们
因此,要修复反序列化程序,请尝试像这样返回子树和当前索引
return root, index
这样调用者就可以像这样更新他们的
root.left, index = deserialize_helper(tree_list, index)
我不能轻易地得到保罗的答案,所以下面是我最终解决问题的方法。感谢Paul帮助我理解不变性和副作用问题,这是主要的bug。我使用了迭代器而不是整数索引
def deserialize(tree_list):
itr = iter(tree_list)
return deserialize_helper(tree_list, itr)
def deserialize_helper(tree_list, itr):
item = next(itr)
if item is None or item == sys.maxsize:
return None
p = Node(item)
p.left = deserialize_helper(tree_list, itr)
p.right = deserialize_helper(tree_list, itr)
return p
与列表不同,INT是不可变的,因此您不能在适当的位置更改它们,这意味着您不能使用它们产生副作用。最简单的方法是让助手返回更新的索引。沿着子树。因此,您可以将新值重新分配给一级索引。@PaulPanzer我是计算机科学新手,我模糊地理解您的意思,但如果您能多解释一下就地和副作用的概念,我将不胜感激。这实际上相当优雅!