队列数据结构支持快速查找第 k 个最大元素

2022-09-02 04:43:30

我遇到了一个问题,它需要一个队列数据结构来支持快速的k个最大元素查找。

此数据结构的要求如下:

  1. 队列中的元素不一定是整数,但它们必须彼此比较,也就是说,当我们比较两个元素时,我们可以分辨出哪一个更大(它们也可以相等)。

  2. 数据结构必须支持排队(在尾部添加元素)和取消排队(删除头部的元素)。

  3. 它可以快速找到队列中第 k 个最大的元素,请注意 k 不是常量。

  4. 您可以假设排队、取消排队和第 k 个最大元素查找的运算都以相同的频率发生。

enter image description here

我的想法是使用修改后的平衡二叉搜索树。该树与普通的平衡二叉搜索树相同,只是每个节点i 都用另一个字段 ni 增强,ni 表示子树中包含的具有根节点i 的节点数。支持上述操作,如下所示:

为简单起见,假设所有元素都是不同的。

Enqueue(x):x首先插入到树中,假设相应的节点是节点t,我们将对(x,指针到节点t)附加到队列中。

取消排队:假设(e1,节点1)是头部的元素,节点1是指向对应于e1的树的指针。我们从树中删除节点1,并从队列中删除(e1,节点1)。

K-th最大元素查找:假设根节点是节点,它的两个子节点是节点和节点(假设它们都存在),我们将K与n个根进行比较,可能会发生三种情况:

  1. 如果 K< n,我们在 n个根的左子树中找到第 K 个最大的元素;

  2. 如果 K>n n,我们在 n个根的右子树中找到(K-n+n)第 1 个最大元素;

  3. 否则 n个根就是我们想要的节点。

所有三个操作的时间复杂度都是O(logN),其中N是当前队列中的元素数。

如何加快上述操作速度?使用什么数据结构以及如何使用?


答案 1

注意 - 你不能为所有人取得更好的成就,充其量你需要“选择”你最关心的操作。(否则,您可以通过将数组馈送到 DS 并查询 1st、2nd、3rd、...第 n 个元素)O(logn)O(n)

  • 使用跳过列表而不是平衡 BST 作为排序结构可以将取消排队的复杂性降低平均情况
    要从跳过列表中删除 - 您需要做的就是使用队列头部的指针访问元素,然后按照链接向上移动并删除每个链接。需要删除的预期节点数为 1 + 1/2 + 1/4 + ... = 2。O(1)
  • 找到Kth可以在O(logK)中实现,方法是从最左边的节点(而不是根)开始,直到你发现你有“更多的儿子,然后需要更多”,然后将刚刚找到的节点视为根,就像问题中的算法一样。虽然它在渐近复杂性方面更好 - 常数因子是双倍的。

答案 2

我发现了一篇有趣的论文:

在VLDB 2008上发布的不确定流的滑动窗口Top-k查询,并被71引用。

https://www.cse.ust.hk/~yike/wtopk.pdf

VLDB是数据库研究领域最好的会议,引用次数证明了数据结构确实有效。

这篇论文看起来相当困难,但如果你真的需要改进你的数据结构,我建议你在本文的参考页阅读这篇论文或几篇论文。