如何证明二叉树确实是二叉搜索树?

时间:2010-08-02 14:02:40

标签: algorithm

给定一个简单的二叉树,我们如何证明树是二叉搜索树?当我们遍历二叉树时,我们如何知道我们所在的节点是否是其父节点的左子节点?我提出了一个解决方案,我将在递归函数调用中传递一些标志,它可以跟踪节点是否是其父节点的左子节点或者我们需要一个父节点指针,通过它我们可以比较: -

if(flag == 'L' && node->value < node->parent->value)
   then continue recursion;
else{
   print "not a binary search tree"
   exit;
}

以同样的方式R需要一个if条件。除此之外你能想到其他任何有效的方法吗?

提前致谢:)

4 个答案:

答案 0 :(得分:5)

我只想查一下:

currentNode.Left.max() < currentNode.ValuecurrentNode.Left.isBinarySearchTree()。如果两者都满足,则它是二叉搜索树。

编辑:

以上操作遍历左侧树两次(一次用于max(),一次用于isBinarySearchTree。但是,只需一次遍历就可以完成:

将最小和最大元素存储在树类中。更新等当然可以在O(1)空间和时间内完成。

然后,不要使用max(),而是创建一个方法isInRange(m,M),检查一个(子)树是否只包含(m,m+1,...,M)范围内的元素。

如下定义isInRange(m,M)

bool isInRange(m,M){
 if (m < currentNode.Value <= M){
  return (currentNode.Left.isInRange(m, currentNode.Value) && currentNode.Right.isInrange(currentNode.Value+1, M));
 }
 return false;
}

然后,初始调用将是root.isInRange(globalmin, globalmax)

没有测试它,所以我不知道它在性能上是否重要。

答案 1 :(得分:5)

简单的答案是执行有序深度优先树遍历并检查节点是否有序。

示例代码(Common Lisp):

(defun binary-search-tree-p (node)
  (let ((last-value nil))
    (labels ((check (value)
               (if (or (null last-value)        ; first checked value
                       (>= value last-value))
                   (setf last-value value)
                   nil))
             (traverse (node)
               (if (null node)
                   t
                   (and (traverse (left node))        ; \
                        (check (value node))          ;  > in-order traversal
                        (traverse (right node))))))   ; /
      (traverse node))))

答案 2 :(得分:3)

您是否已经有办法迭代/遍历树的元素?然后,您可以简单地遍历树并检查每个元素是否大于前一个元素

答案 3 :(得分:2)

您可以在树上进行深度优先搜索,而无需在一次传递中缓存每个子树的最小值和最大值,但是您必须要小心,因为比较它们之间的值和父级及其子级之间的值不是足够。例如,在树中:

(10
   (7
     nil
     (20 nil nil)
   )
   nil
)

根(10)的左子(7)满足不等式(7 <= 10),7(20> = 7)的右子(20)也是如此。但是,树不是BST(二进制搜索树),因为20不应该在10的左子树中。

要解决此问题,您可以执行遍历传递给额外参数,指定子树的有效间隔。

// The valid interval for the subtree root's value is (lower_bound, upper_bound).
bool IsBST(const node_t* tree, int lower_bound, int upper_bound) {
  if (tree == NULL) return true;  // An empty subtree is OK.
  if (tree->value <= lower_bound) return false;  // Value in the root is too low.
  if (tree->value >= upper_bound) return false;  // Value in the root is too high.

  // Values at the left subtree should be strictly lower than tree->value
  // and be inside the root valid interval.
  if (!IsBST(tree->left, lower_bound, tree->value))
    return false;

  // Values at the left subtree should be strictly greater than tree->value
  // and be inside the root valid interval.
  if (!IsBST(tree->right, tree->value, upper_bound))
    return false;

  // Everything is OK, it is a valid BST.
  return true;  
}

请注意,通过保持原始有效间隔,函数将检测到该位置的20无效,因为它不在内部(7,10)。第一次调用应该以无限间隔完成,例如:

IsBST(tree, INT_MIN, INT_MAX);

希望这有帮助。