到目前为止,我知道像AVL树和红黑树这样的自平衡BST可以在O(log n)次执行这些操作。
但是,要使用这些结构,我们必须自己实现AVL树或RB树。
我听说有这四种操作的算法/实现,而不使用自平衡BST。
使用我们自己定义的结构,我们需要编写这么多行。但是,我听说有可能在不到100行代码中支持这四个运算符:\
你们对于如何做到这一点有什么想法吗?
除了BST,还有其他可能的选择吗?
答案 0 :(得分:3)
如评论中所述,如果要维护一组整数,并且可以将坐标压缩作为预处理步骤(例如,因为您的算法处于脱机状态并且知道将来的所有查询),您可以使用{{ 3}}支持每次操作在O(log n)中插入/删除/排名/选择数字。这是C ++中的一个例子:
int tree[N]; // where N is the number of compressed coordinates
const int maxl = floor(log(N)/log(2));
void insert(int i) { // 1 <= i <= N
for (; i <= N; i += i & -i) ++tree[i];
}
void remove(int i) { // 1 <= i <= N
for (; i <= N; i += i & -i) --tree[i];
}
int rank(int i) { // 1 <= i <= N
int sum = 0;
for (; i; i -= i & -i) sum += tree[i];
return sum;
}
int select(int k) { // k is 1-based
int ans = 0, s = 0;
for (int i = maxl; i >= 0; --i) // maxl = largest i s.t. (1<<i) <= N
if (s + tree[ans + (1<<i)] < k) {
ans += 1<<i;
s += tree[ans];
}
return ans+1;
}
select
功能有些神奇。它重用高位的结果来计算O(1)中ans + (1<<i)
的前缀和,这是非常酷的IMHO :)这样它只需要时间O(log n),而不是O(log ^ 2 n)使用标准二分查找很容易实现。