[英]Check is a tree in python is a Binary Search tree
我想写一个 function 来显示给定的树是否为 BinarySearch。
这是我到目前为止写的:
class Node:
def _isBinary(self):
L=[]
if self.left is not None and self.right is not None:
if self.left.data>self.data or self.right.data<self.data:
L.append(1)
else:
L+=self.left._isBinary()
L+=self.right._isBinary()
else:
if self.left is not None:
if self.left.data>self.datat:
L.append(1)
else:
self.left._isBinary()
if self.right is not None:
if self.right.data<self.data:
L.append(1)
else:
self.right._isBinary()
return L
class tree:
def isBinary(self):
if self.root is None:
return
else:
return not 1 in self.root._isBinary(self.root.data)
(显然,我只是报告了代码中感兴趣的部分)这段代码运行良好,但给出了错误的答案,例如,一个数字(大于根)位于树的左侧,但它是一个较低的数字:
99
/ \
8 888
\
100
它应该给我 False,而不是返回 True。 我能做什么? (如果可能的话,不完全改变我的原始代码?)
另一种方法是只对 BST 进行中序遍历,然后检查它是否已排序。 BST的中序遍历是排序的。
def inorder(node):
if node is None:
return
yield from inorder(node.left)
yield node.data
yield from inorder(node.right)
inorder_traversal = list(inorder(root))
print(all(i<=j for i, j in zip(inorder_traversal, inorder_traversal[1:]))) # check if sorted
由于all
的短路特性,您可以引入itertools.tee
以获得更好的性能。
inorder_traversal = inorder(root)
a, b = tee(inorder_traversal) # copy the `inorder_traversal` iterator
next(b) # discard first element
print(all(i<=j for i, j in zip(a,b))) # check if sorted
有关tee
如何工作的更多信息,您可以参考这个答案Iterate a list as pair (current, next) in Python 。
遵循以下思路的一些方法应该有效:
class Node:
def is_binary_search(self, lo=None, hi=None):
if lo is not None and lo > self.data:
return False
if hi is not None and hi < self.data:
return False
if self.left and not self.left.is_binary_search(lo=lo, hi=self.data):
return False
if self.right and not self.right.is_binary_search(lo=self.data, hi=hi):
return False
return True
您将那些已知的子树边界( lo
和hi
)传递给递归调用。
您可以按顺序遍历树并检查值是否在升序。 使用迭代器将避免创建任何列表的需要。
def iter(self):
if self.left: yield from self.left.iter()
yield self
if self.right: yield from self.right.iter()
from itertools import islice
def isBinary(self):
return all(a<b for a,b in zip(self.iter(),islice(self.iter(),1,None)))
假设一个节点是这样定义的
class Node:
def __init__(self, value, left=None, right=None):
self.value = value
self.right = right
self.left = left
这个简单的递归 function 应该足够了。 将左右子树的两个不同比较器函数作为可调用参数传递给内部递归 function。这不是最短的解决方案,但看起来不像黑魔法(希望如此)。
def is_bst(root):
def is_bst_recursive(node, in_order):
if node is None:
return True
if not in_order(node.value):
return False
if node.left and node.left.value >= node.value:
return False
if node.right and node.right.value <= node.value:
return False
return (is_bst_recursive(node.left, in_order)
and is_bst_recursive(node.right, in_order))
return (is_bst_recursive(root.left, lambda x: x < root.value)
and is_bst_recursive(root.right, lambda x: x > root.value))
我们可以编写is_binary_search
,它接受一个输入树t
和一个默认为True
的compare
function -
def is_binary_search(t, compare = lambda _: True):
if not t:
return True
else:
return compare(t.data) \
and is_binary_search(t.left, lambda l: compare(l) and l < t.data) \
and is_binary_search(t.right, lambda r: compare(r) and r > t.data)
我们创建两棵树来测试我们的 function -
t1
,一个无效的二叉搜索树,在您的示例问题中提供t2
,一个有效的二叉搜索树class node:
def __init__(self, data, left = None, right = None):
self.data = data
self.left = left
self.right = right
t1 = \
node(99, node(8, None, node(100)), node(888))
# 99
# / \
# 8 888
# \
# 100
t2 = \
node(99, node(8, None, node(10)), node(888))
# 99
# / \
# 8 888
# \
# 10
print(is_binary_search(t1)) # False
print(is_binary_search(t2)) # True
我们还应该测试空树、 None
和只有一个节点的树,每个都是有效的二叉搜索树 -
print(is_binary_search(None)) # True
print(is_binary_search(node(123))) # True
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.