[英]Build binary search tree using dictionary in Python
我正在尝试在 python 中使用 dict 构建 BST(二叉搜索树)。 我不明白为什么我的代码没有向 BST 添加节点。 我在这里看到了一个类似的帖子: 如何在 Python 中实现二叉搜索树? 除了声明一个节点 class 之外,它看起来与我的代码相同,但我想知道为什么我的 dict 实现失败(并希望提高我对在 python 中使用递归传递参数的理解)。
keys = [10,9,2,5,3,7,101,18]
start = {'key': keys[-1], 'val': 1, 'left': None, 'right': None}
def binarySearch(root, node):
# compare keys and insert node into right place
if not root:
root = node
elif node['key'] < root['key']:
binarySearch(root['left'], node)
else:
binarySearch(root['right'], node)
# Now let's test our function and build a BST
while keys:
key = keys.pop()
node = {'key': key, 'val': 1, 'left': None, 'right': None}
binarySearch(start, node)
print(start) # unchanged, hence my confusion. Thx for your time!
============================================
编辑:这是使它工作的代码!
def binarySearch(root, node):
# compare keys and insert node into right place
if not root:
root = node
elif node['key'] < root['key']:
if not root['left']: root['left'] = node
else: binarySearch(root['left'], node)
else:
if not root['right']: root['right'] = node
else: binarySearch(root['right'], node)
这是我认为在幕后发生的事情(为什么一个版本能够添加到 BST 而另一个版本不能):
在原始版本中,我们将到达一个递归调用,其中root
仍然指向 BST 内部的 None,但随后root = node
使root
指向与start
绝对没有连接的node
,即 BST 本身。 然后局部变量被删除并且不做任何改变。
在修改后的版本中,我们将避免这种情况,因为当我们通过例如root['left'] = node
添加节点时。 这里root
仍然指向原始 BST,因此我们正在修改原始 BST 中的 key-val 对,而不是让root
指向完全在 BST 之外的东西。
让我们像 python 解释器一样运行您的代码。
让我们从第一次调用开始: binarySearch(start, node)
这里start
是在脚本顶部定义的dict
,而node
是另一个dict
(奇怪的是它具有相同的值)。
让我们跳入调用,我们发现自己在: if not root:
其中root
指的是上面的start
,所以是truthy
,所以if
失败了。
接下来我们发现自己在: elif node['key'] < root['key']:
在这种情况下不是True
。
接下来我们传递到else:
我们在: binarySearch(root['right'], node)
。
就在我们跳入第一个递归调用之前,让我们回顾一下调用的参数是什么:从start
的root['right']
的值为None
并且node
仍然是我们想要插入某处的同一个dict
。 因此,进入递归调用。
我们再次发现自己处于: if not root:
然而这次root
只是指第一个递归调用的第一个参数,我们可以从上面对参数的回顾中看到root
指的是None
。
现在None
被认为是falsy
的,所以这次if
成功了,我们进入下一行。
现在我们在root = node
。
这是 python 中的分配。 这意味着 python 将使用变量root
停止引用None
并引用当前引用的任何node
,这是在while
循环中创建的dict
。 所以root
(这只是一个参数,但你现在可以将其视为局部变量)指的是dict
。
现在发生的事情是我们在第一个递归调用的末尾,这个 function 结束了。 每当 function 结束时,所有局部变量都会被销毁。 即root
和node
被破坏。 那只是这些变量,而不是它们所指的内容。
现在我们回到第一个调用站点之后,即在binarySearch(root['right'], node)
之后
我们可以在这里看到参数: root['right'], node
仍然引用它们之前引用的任何内容。 这就是为什么你的start
没有改变以及为什么你的程序应该right
处理left
而不是递归的原因。
#Creted by The Misunderstood Genius
def add_root(e,key):
''''
e is node's name
key is the node's key search
'''
bst=dict()
bst[e]={'key':key,'P':None,'L':None,'R':None}
return bst
def root(tree):
for k,v in tree.items():
if v['P'] == None:
return k
def insert(tree, node, key):
tree[node]={'key':key,'P':None,'L':None,'R':None}
y =None
x = root(tree)
node_key = tree[node]['key']
while x is not None:
y=x
node_root=tree['R']['key']
if node_key < node_root:
x=tree[x]['L']
else:
x=tree[x]['R']
tree[node]['P']=y
if y is not None and node_key< tree[y]['key']:
tree[y]['L']=node
else:
tree[y]['R']=node
return tree
def print_all(tree):
for k,v in tree.items():
print(k,v)
print()
'''
Give a root node and key search target
Returns the name of the node with associated key
Else None
'''
def tree_search(tree,root, target):
if root ==None:
print(" key with node associate not found")
return root
if tree[root]['key'] == target:
return root
if target < tree[root]['key']:
return tree_search(tree,tree[root]['L'],target)
else:
return tree_search(tree,tree[root]['R'],target)
def tree_iterative_search(tree,root,target):
while root is not None and tree[root]['key']!=target:
if target < tree[root]['key']:
root=tree[root]['L']
else:
root=tree[root]['R']
return root
def minimum(tree,root):
while tree[root]['L'] is not None:
root=tree[root]['L']
return tree[root]['key']
bst=add_root('R',20)
bst=insert(bst,'M',10)
bst=insert(bst,'B',8)
bst=insert(bst,'C',24)
bst=insert(bst,'D',22)
bst=insert(bst,'E',25)
bst=insert(bst,'G',25)
print_all(bst)
print(tree_search(bst,'R',25))
x=tree_iterative_search(bst,'R',25)
print(x)
#print(minimum(bst,'R'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.