Check是Python中的一棵树是二叉搜索树

问题描述 投票:0回答:6

我想编写一个函数来显示给定的树是否是 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。我能做些什么? (如果可能的话,不完全改变我原来的代码?)

python recursion tree binary-tree
6个回答
7
投票

另一种方法是对 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

由于

itertools.tee
的短路性质,您可以引入
all
以获得更好的性能。

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
如何工作的更多信息,您可以参考这个答案在Python中将列表作为对(当前,下一个)迭代。


1
投票
以下一些方法应该有效:

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
)传递给递归调用。


1
投票
您可以按顺序遍历树并检查值是否升序。使用迭代器将避免创建任何列表的需要。

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)))
    

1
投票
假设一个节点是这样定义的

class Node: def __init__(self, value, left=None, right=None): self.value = value self.right = right self.left = left
这个简单的递归函数应该足够了。
将左子树和右子树的两个不同的比较器函数作为可调用参数传递给内部递归函数。
这不是最短的解决方案,但看起来不像黑魔法(希望如此)。

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))
    

0
投票
我们可以编写

is_binary_search

 ,它接受输入树 
t
 和一个 
compare
 函数,默认始终为 
True
 -

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)
我们创建两棵树来测试我们的功能 - 

  • 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
    

0
投票
def isbst(self,root): if (root is None ): return True if(root is not None): if (root.left is not None and root.left.data>=root.data): return False if (root.right is not None and root.right.data<root.data): return False return self.isbst(root.left) and self.isbst(root.right)
    
© www.soinside.com 2019 - 2024. All rights reserved.