AVL树:在O(logn)时间内在两个值之间的键中查找具有最小数据值的键

时间:2014-10-07 23:08:21

标签: algorithm pseudocode avl-tree

所以我给了一个AVL树。并且我试图找出至少伪代码以找到具有两个值k1和k2之间的所有键中的最小数据值的密钥。这假设存储在每个节点中的字段数据是整数。我想确保我的伪代码在O(logn)时间内运行。

我知道我可以通过在节点结构中存储一个额外字段来实现它。并显示在更新期间如何维护此字段,但我不知道从那里去哪里。

1 个答案:

答案 0 :(得分:0)

假设节点结构看起来像这样(Java)。

class Node {
    Node left;
    Node right;
    int key;
    int value;
    int tree_max;
}

tree_max的重复发生是

node.tree_max == max(node.value, node.left.tree_max, node.right.tree_max),

当滥用表示法时,node.left.tree_max为空时省略node.leftnode.right.tree_max为空时省略node.right。每次我们写入节点时,我们可能必须更新其所有祖先。我不会写伪代码,因为如果没有编译器,我很可能会错误。

要查找密钥k1k2之间的最大值,我们首先找到这些节点的最不常见的祖先。

Node lca = root;
while (lca != null) {
    if (lca.key < k1) { lca = lca.left; }
    else if (k2 < lca.key) { lca = lca.right; }
    else { break; }
}

现在,如果lca为null,则范围为空,我们应该返回minus无穷大或抛出异常。否则,我们需要找到最多三个范围:k1包含lca独占,lca本身和lca独占k2包含。我会将k1包含的代码提供给lca独占代码;其他两个范围分别是平凡和对称的。我们将finger移到树下,就像我们正在搜索k1一样,将最大值累加到left_max

int left_max = /* minus infinity */;
Node finger = lca.left;
while (finger != null) {
    if (k1 <= finger.key) {
        left_max = max(left_max, finger.value);
        if (finger.right != null) { left_max = max(left_max, finger.right.tree_max); }
        finger = finger.left;
    } else { finger = finger.right; }
}