怎样判断一个二叉树是binary search tree

本文详细介绍了如何通过中序遍历来判断一个二叉树是否为二叉搜索树,并提供了两种解决方案:一种是递归检查每个节点的值是否在其允许范围内,另一种是中序遍历并检查节点值是否有序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

怎样判断一个二叉树是binary search tree

怎么实现 boolean isBST(Node *root)?
看看这个,简单明了
http://www.ardendertat.com/2011/10/10/programming-interview-questions-7-binary-search-tree-check/

In-order traverse能够按顺序打印BST的,所以只需要按照in-order traverse
走一遍,同时记录last visited node value,保证当前node的值比最后一个大
就是BST了。

Programming Interview Questions 7: Binary Search Tree Check
Posted on October 10, 2011 by Arden

This is a very common interview question. Given a binary tree, check whether it’s a binary search tree or not. Simple as that..

The first solution that comes to mind is, at every node check whether its value is larger than or equal to its left child and smaller than or equal to its right child (assuming equals can appear at either left or right). However, this approach is erroneous because it doesn’t check whether a node violates any condition with its grandparent or any of its ancestors. The following tree would be incorrectly classified as a binary search tree, the algorithm won’t be able to detect the inconsistency between 3 and 4:

        3

      /    \

   2       5

   /\

1   4

So, we should keep track of the minimum and maximum values a node can take. And at each node we will check whether its value is between the min and max values it’s allowed to take. The root can take any value between negative infinity and positive infinity. At any node, its left child should be smaller than or equal than its own value, and similarly the right child should be larger than or equal to. So during recursion, we send the current value as the new max to our left child and send the min as it is without changing. And to the right child, we send the current value as the new min and send the max without changing. This approach leads to the following code:

class Node:
    def __init__(self, val=None):
        self.left, self.right, self.val = None, None, val
 
INFINITY = float("infinity")
NEG_INFINITY = float("-infinity")
 
def isBST(tree, minVal=NEG_INFINITY, maxVal=INFINITY):
    if tree is None:
        return True
 
    if not minVal <= tree.val <= maxVal:
        return False
 
    return isBST(tree.left, minVal, tree.val) and \
           isBST(tree.right, tree.val, maxVal)

There’s an equally good alternative solution. If a tree is a binary search tree, then traversing the tree inorder should lead to sorted order of the values in the tree. So, we can perform an inorder traversal and check whether the node values are sorted or not. Here is the code:

def isBST2(tree, lastNode=[NEG_INFINITY]):
    if tree is None:
        return True
 
    if not isBST2(tree.left, lastNode):
        return False
 
    if tree.val < lastNode[0]:
        return False
 
    lastNode[0]=tree.val
 
    return isBST2(tree.right, lastNode)

I personally like this question a lot because it’s simple (but not trivial) and demonstrates the basic knowledge of binary search trees and tree traversals.

As for the in order traversal above: where are you adding to the node list?
A special note about these types of problems when interviewing at Microsoft: while algorithmically your solution should be recursive, your implementation should be prefixed by: “the problem with the recursive implementation is that it’s only good when you know the depth, otherwise you can easily blow the stack”. This shows you understand the practical difference between writing code in a classroom and in a production environment. If the interviewer then says: “let’s say you don’t need to worry about that”, you proceed with your solution, but twice in my own experience the problem was precisely about whether I would just rush to implement the obvious and well known book solution, or stop to consider the real world implications.

You’re right about recursion and stack space. I didn’t mention that because both of the algorithms are recursive. If we would like to code it iteratively, than we have to maintain a queue, which will use the heap space. But as you said, it’s definitely useful to first step back and thoroughly analyze all the possible solutions with their real world implications, and then start coding the actual algorithm.

There’s no reason to build a list of all node values in isBST2. You only need the value of the last node visited so far. Rename nodes to maxValBox and update it like this:

maxValBox[0] = tree.val
<think>嗯,用户想了解关于完整二叉搜索树的概念和实现方法。首先,我需要明确什么是完整二叉搜索树(Complete Binary Search Tree,CBST)。根据之前学过的知识,二叉树中的完全二叉树(Complete Binary Tree)是指除了最后一层外,其他层都是满的,并且最后一层的节点都尽可能靠左排列。而二叉搜索树(Binary Search Tree,BST)的特点是每个节点的左子树所有节点的值都小于该节点的值,右子树则都大于。所以完整二叉搜索树应该是结合了这两种特性的数据结构,即同时满足完全二叉树的结构和二叉搜索树的排序性质。 接下来,我需要确认完整二叉搜索树的具体定义和特点。完全二叉树的特性使得它可以用数组高效地存储,而不需要指针,这对于内存管理是有优势的。而二叉搜索树的特性则保证了高效的查找、插入和删除操作,平均时间复杂度为O(log n)。结合起来,CBST可能在保持高效操作的同时,优化存储结构。不过,用户可能想知道如何实现这样的数据结构,或者它的具体应用场景。 然后,实现方法方面,可能需要考虑如何构建这样的树。由于是完全二叉树,节点的位置可以通过数组的索引来确定,比如对于节点i,左子节点在2i+1,右子节点在2i+2。同时,作为二叉搜索树,必须满足左子树的值小于根节点,右子树的值大于根节点。因此,构建CBST可能需要将给定的有序数组按照完全二叉树的结构进行排列。例如,对于有序数组,中序遍历完全二叉树的结构应该能得到有序序列,因此可能需要找到中间节点作为根,递归构建左子树和右子树。 另外,用户可能关心插入和删除操作在CBST中的处理。因为完全二叉树的结构要求最后一层尽可能左对齐,插入和删除可能需要调整树的结构以维持完全性,这可能会影响二叉搜索树的性质。这时候可能需要特定的算法来保持两者的平衡,或者在某些情况下,CBST可能更适合静态数据,而不是频繁变动的数据,因为维护结构可能代价较高。 还需要考虑CBST与其他类型二叉搜索树的区别,比如平衡二叉搜索树(如AVL树、红黑树)。CBST可能在存储上更紧凑,但可能在动态操作上不如平衡树高效。因此,用户可能想知道在什么情况下选择CBST更合适,比如数据静态且需要快速查找的情况下。 此外,用户的问题中提到了“实现方法”,可能需要给出具体的代码示例,比如如何从有序数组构建CBST,或者如何插入节点。例如,可以通过递归方法,每次选择中间元素作为根节点,然后递归构建左右子树,确保完全二叉树的结构。这部分需要结合算法步骤和代码实现来说明。 最后,需要验证自己的理解是否正确,是否有遗漏或错误的地方。例如,是否混淆了完全二叉树和满二叉树的概念,或者是否正确处理了二叉搜索树的排序性质与完全二叉树结构之间的冲突。比如,在构建过程中,如何确保节点位置既满足完全性,又满足左小右大的顺序,可能需要特定的构建策略,如中序遍历填充。</think>### 完整二叉搜索树(Complete Binary Search Tree)概念解析 完整二叉搜索树是**完全二叉树**和**二叉搜索树**的结合体,需同时满足以下特性: 1. **完全二叉树结构**:所有层除最后一层外均为满层,最后一层节点左对齐排列[^1] 2. **二叉搜索树性质**:任意节点的左子树值均小于该节点,右子树值均大于该节点 $$ \text{设节点索引为}i,\ \text{左子节点索引}=2i+1,\ \text{右子节点索引}=2i+2 $$ ### 核心实现步骤(以数组存储为例) 1. **数据预处理**:将输入数据排序为升序序列 2. **递归构建**: ```python def build_cbst(sorted_arr, tree, root_index=0): if not sorted_arr: return n = len(sorted_arr) mid = n // 2 # 计算中间索引 tree[root_index] = sorted_arr[mid] # 递归构建左子树(左半部分) build_cbst(sorted_arr[:mid], tree, 2*root_index+1) # 递归构建右子树(右半部分) build_cbst(sorted_arr[mid+1:], tree, 2*root_index+2) ``` 3. **空间分配**:根据完全二叉树特性预分配数组空间 $$ \text{数组长度}=2^h-1\ \text{(h为树的高度)} $$ ### 关键特性对比 | 特性 | 普通BST | 完整BST | |---------------------|---------|--------------| | 空间利用率 | 动态 | 100%(数组) | | 查找时间复杂度 | O(h) | O(log n) | | 插入/删除复杂度 | O(h) | O(n) | | 适合场景 | 动态数据| 静态数据 | ### 应用场景 1. 预先生成的静态数据集快速查询(如字典数据) 2. 需要固定存储空间的嵌入式系统 3. 需要快速序列化/反序列化的场景[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值