插入/删除/排名/选择查询的最佳数据结构/算法

时间:2014-02-14 13:27:51

标签: algorithm binary-search-tree

到目前为止,我知道像AVL树和红黑树这样的自平衡BST可以在O(log n)次执行这些操作。

但是,要使用这些结构,我们必须自己实现AVL树或RB树。

我听说有这四种操作的算法/实现,而不使用自平衡BST。

使用我们自己定义的结构,我们需要编写这么多行。但是,我听说有可能在不到100行代码中支持这四个运算符:\

你们对于如何做到这一点有什么想法吗?

除了BST,还有其他可能的选择吗?

1 个答案:

答案 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)使用标准二分查找很容易实现。