在二叉搜索树中查找非法节点

时间:2014-12-18 14:34:44

标签: algorithm data-structures tree binary-search-tree

我想在二元搜索树中找到一个节点 - v,它满足以下条件中的一个(且只有一个):

  • v的左子树包含至少一个小于v
  • 的值
  • v的右子树包含至少一个大于v
  • 的值

我知道我的树中只存在一个节点v - T,我想找到它。

我想到了这个算法,给出了一个树T:

  1. 检查T的左子是否大于根,或者如果T的右子小于根,如果其中一个条件为真,则返回根。
  2. 否则,请检查T的左右子树,假设它们存在。如果它们都不存在,则意味着我们到达了一个叶子并返回-1(不应该发生)
  3. 所以我的第一个问题是:算法是否正确?它做了它的假设吗? 其次,我需要及时复杂O(n)这种情况发生了吗?

    如果我错了,我很乐意为这个问题找到一个有效的算法

2 个答案:

答案 0 :(得分:2)

您可以通过将条件转换为代码来完全实现算法:

boolean hasValueSmallerThan(Vertex startFrom, int value) {
    return
        this.value < value
    ||  (startFrom.left != null && hasValueSmallerThan(startFrom.left, value))
    ||  (startFrom.right != null && hasValueSmallerThan(startFrom.right, value));
}
boolean hasValueGreaterThan(Vertex startFrom, int value) {
    return
        this.value > value
    ||  (startFrom.left != null && hasValueGreaterThan(startFrom.left, value))
    ||  (startFrom.right != null && hasValueGreaterThan(startFrom.right, value));
}
Vertex findInvalid(Vertex startFrom) {
    if (startFrom.left == null && startFrom.right == null) {
        return null;
    }
    // v's right subtree includes at least one value that is bigger than v
    if (startFrom.left == null) {
        boolean checkRight = hasValueGreaterThan(startFrom.right, this.value);
        return (checkRight) ? this : findInvalid(startFrom.right);
    }
    // v's left subtree includes at least one value that is smaller than v
    if (startFrom.right == null) {
          boolean checkLeft = hasValueSmallerThan(startFrom.left, this.value);
          return (checkLeft) ? this : findInvalid(startFrom.left);
    }
    // If we are here, both subrtees are non-null
    boolean leftIsInvalid = hasValueSmallerThan(startFrom.left, this.value);
    boolean rightIsInvalid = hasValueGreaterThan(startFrom.right, this.value);
    // Return XOR of the two checks, which means "one of the two is true, but not both"
    if (leftIsInvalid ^ rightIsInvalid) {
        return this;
    }
    Vertex leftFind = findInvalid(startFrom.left);
    if (leftFind != null) return leftFind;
    return findInvalid(startFrom.right);
}

这个实现非常简单:它有两个递归助手hasValueSmallerThanhasValueGreaterThan,它们由递归findInvalid使用。

当大多数代码处理两个子树中的一个为空时的情况。除此之外,它可以直接将需求转换为代码。

答案 1 :(得分:1)

你的算法没有按照预期的那样做。考虑以下树:

       3
      / \
     2   5
    / \
   1   4

没有节点有一个违反排序的子节点,但根的左子树包含的值大于根。