Python专家,
我一直在尝试使用Python实现BST,这是我的插入函数代码:
草案1:
def insert(self, val):
newNode = self._Node(val)
if (self._root is None):
self._root = newNode
else:
self._insert(self._root,val)
def _insert(self, node, val):
if node is None:
node = self._Node(val)
elif val >= node._val:
self._insert(node._right, val)
else:
self._insert(node._left, val)
但是,除了root之外,我无法构建树。我猜测我通过两个函数传递参数搞砸了,因为当我修改下面的代码时,我明白了:
草案2:
def insert(self, val):
newNode = self._Node(val)
if (self._root is None):
self._root = newNode
else:
self._insert(self._root,val)
def _insert(self, node, val):
if val >= node._val:
if node._right is None:
node._right = self._Node(val)
else:
self._insert(node._right, val)
else:
if node._left is None:
node._left = self._Node(val)
else:
self._insert(node._left, val)
我努力理解为什么草案2有效,但草案1没有。这里有什么帮助?提前谢谢!
答案 0 :(得分:2)
您的根本误解是变量分配如何工作并与Python的评估策略相互作用:call-by-sharing.
基本上,在您的初稿中,当您执行以下操作时:
def _insert(self, node, val):
if node is None:
node = self._Node(val)
...
您只是将名称(变量)node
分配给self._Node(val)
的值,但是当您离开范围时,新对象将被销毁!即使node
用于引用方法调用传入的值,简单赋值也不会改变名称引用的对象,而是重新分配名称。< / em>的
然而,在你的第二稿中:
def _insert(self, node, val):
if val >= node._val:
if node._right is None:
node._right = self._Node(val)
else:
self._insert(node._right, val)
你正在改变一个对象,即:`node._right = self._Node(val)
这是一个简单的例子,希望有启发性:
>>> def only_assign(object):
... x = 3
... object = x
...
>>> def mutate(object):
... object.attribute = 3
...
>>> class A:
... pass
...
>>> a = A()
>>> a
<__main__.A object at 0x7f54c3e256a0>
>>> only_assign(a)
>>> a
<__main__.A object at 0x7f54c3e256a0>
>>> mutate(a)
>>> a.attribute
3
答案 1 :(得分:1)
我相信这是因为这样做:
node = self._Node(val)
在_insert函数中,您不是更改左/右节点的值,而是将名称节点绑定到新的_Node对象,从而使左/右节点为None。
在您的第二个草稿中,您实际上正在影响左/右节点的新对象。
这是一个简单的例子来说明您的代码会发生什么。
猜猜打印(测试)会显示什么?
test = [5, 5, 5]
def function(list):
list[0] = 10
list = range(1, 3)
function(test)
print test
如果你认为它会显示[1,2]你错了..它实际上会显示[10,5,5]因为当做list = range(1,3)时我们将名字列表绑定到另一个对象,而不是更改它绑定的第一个对象(一个测试实际上绑定到)