结构类似优先级队列,但具有类似下界的内容

Structure like priority queue but with something like lower bound

本文关键字:优先级 队列 结构      更新时间:2023-10-16

我想要一个结构来存储(例如)数字,我可以在其中插入和删除元素,我的结构始终保持排序(就像优先级队列一样),但有可能知道给定数字的位置,以及对数时间内的每一次操作。

也许使用lower_bound、upper_bound,或者只是二进制搜索,但在priority_queue中,阻碍我进行二进制搜索的是,我无法访问带有索引的元素,只能访问第一个索引。

我认为您正在寻找一个订单统计树,一个支持时间O(logn)中所有常规BST操作的增强BST,以及另外两个:

  • rank(elem):返回elem将在排序序列中占据哪个索引
  • index(k):给定一个索引k,返回排序序列中该索引处的元素

上述两个操作在O(logn)时间内运行,速度极快。

您可以将订单统计树视为优先级队列。插入与正常的BST插入一样工作,要提取最低/最高的元素,只需从树中删除最小/最大的元素,您只需沿着树的左或右脊椎向下走,就可以在时间O(logn)内完成这一操作。

优先级队列不会按顺序排列。至少,不是典型的。优先级队列使您可以快速获得序列中的下一个项目。但是,您无法有效地访问队列中的第5个项目。

我知道有三种不同的方法可以建立一个优先级队列,在这个队列中你可以通过密钥有效地访问项目:

  • 使用平衡的二进制搜索树来实现队列。尽管所有操作都是O(logn),但典型的运行时间比二进制堆慢
  • 将堆优先级队列实现为跳过列表。这是一个不错的选择。我看到一些人报告说,跳过列表优先级队列的性能优于二进制堆。搜索[C++跳过列表]会返回许多实现
  • 我所说的索引二进制堆也可以。基本上,您将散列映射或字典与二进制堆结合在一起。映射按键进行索引,其值包含堆数组中项的索引。这样的东西不难建造,而且非常有效
  • 仔细想想,你可以制作任何类型堆的索引版本

您有很多选择。我自己也很喜欢跳过列表,但你的里程数可能会有所不同。

正如我所指出的,索引二进制堆是一种混合数据结构,它维护一个字典(哈希图)和一个二进制堆。简要介绍它的工作原理:

dictionary键是用于查找放入堆中的项的字段。该值是一个整数:堆中该项的索引。

堆本身是一个在数组中实现的标准二进制堆。唯一的区别是,每次将项从堆中的一个位置移动到另一个位置时,都会更新它在字典中的位置。因此,例如,如果交换两个项,则不仅要交换数组中的项本身,还要交换它们在字典中存储的位置。例如:

heap is an array of string references
dict is a dictionary, keyed by string
swap (a, b)
{
// swap item at heap[a] with item at heap[b]
temp = heap[a]
heap[a] = heap[b]
heap[b] = temp
// update their positions in the dictionary
dict[heap[a]] = b
dict[heap[b]] = a
}

这是对标准二进制堆实现的一个非常简单的修改。每次移动项目时,您只需要小心更新位置

您也可以使用基于节点的堆来实现这一点,如Pairing堆、Fibonacci堆、Skew堆等。