所以我给了一个AVL树。并且我试图找出至少伪代码以找到具有两个值k1和k2之间的所有键中的最小数据值的密钥。这假设存储在每个节点中的字段数据是整数。我想确保我的伪代码在O(logn)时间内运行。
我知道我可以通过在节点结构中存储一个额外字段来实现它。并显示在更新期间如何维护此字段,但我不知道从那里去哪里。
答案 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.left
,node.right.tree_max
为空时省略node.right
。每次我们写入节点时,我们可能必须更新其所有祖先。我不会写伪代码,因为如果没有编译器,我很可能会错误。
要查找密钥k1
和k2
之间的最大值,我们首先找到这些节点的最不常见的祖先。
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; }
}