简体   繁体   English

优先级队列之类的结构,但下限类似

[英]Structure like priority queue but with something like lower bound

I want a structure to store (for example) numbers where I can insert and remove elements, my structure remains sorted always (like a priority queue) BUT with the possibility of knowing where is a given number, and every operation in logarithmic time. 我想要一个结构来存储(例如)我可以在其中插入和删除元素的数字,我的结构始终保持排序(就像优先级队列一样),但是可以知道给定数字在哪里,并且每个操作都以对数时间进行。

Maybe with lower_bound, upper_bound, or just a binary search, but in priority_queue what blocks me to do binary search is that I cannot access the elements with an index, only the first one. 也许使用lower_bound,upper_bound或仅进行二进制搜索,但是在priority_queue中,阻止我进行二进制搜索的原因是我无法访问只有第一个索引的元素。

A priority queue does not keep things in sorted order. 优先级队列不会使事物保持排序。 At least, not typically. 至少,不是通常。 A priority queue makes it possible for you to quickly obtain the next item in the sequence. 优先级队列使您可以快速获取序列中的下一项。 But you can't efficiently access, say, the 5th item in the queue. 但是您无法有效地访问队列中的第五项。

I know of three different ways to build a priority queue in which you can efficiently access items by key: 我知道三种建立优先级队列的方法,在这些队列中,您可以通过键有效地访问项目:

  • Use a balanced binary search tree to implement the queue. 使用平衡的二进制搜索树来实现队列。 Although all operations are O(log n), typical running time is slower than a binary heap. 尽管所有操作均为O(log n),但典型的运行时间比二进制堆慢。
  • Implement the heap priority queue as a skip list . 将堆优先级队列实现为跳过列表 This is a good option. 这是一个不错的选择。 I've seen some people report that a skip list priority queue outperforms a binary heap. 我见过有人报告说,跳过列表优先级队列的性能优于二进制堆。 A search for [C++ skip list] will return you lots of implementations. 搜索[C ++跳过列表]将返回许多实现。
  • What I call an indexed binary heap also works. 我所谓的索引二进制堆也可以工作。 Basically, you marry a hash map or dictionary with a binary heap. 基本上,您将哈希映射或字典与二进制堆结合在一起。 The map is indexed by key, and its value contains the index of the item in the heap array. 该映射由键索引,其值包含堆数组中该项的索引。 Such a thing is not difficult to build, and is quite effective. 这样的东西并不难构建,并且非常有效。
  • Come to think of it, you can make an indexed version of any type of heap. 想一想,您可以为任何类型的堆创建索引版本。

You have a number of options. 您有很多选择。 I rather like the skip list, myself, but your mileage may vary. 我个人比较喜欢跳过列表,但是您的里程可能会有所不同。

The indexed binary heap, as I pointed out, is a hybrid data structure that maintains a dictionary (hash map) and a binary heap. 正如我所指出的那样,索引的二进制堆是一种混合数据结构,它维护一个字典(哈希图)和一个二进制堆。 Briefly how it works: 简要说明其工作原理:

The dictionary key is the field that you use to look up an item that you put into the heap. 字典关键字是用于查找放入堆中的项目的字段。 The value is an integer: the index of that item in the heap. 该值是一个整数:该项目在堆中的索引。

The heap itself is a standard binary heap implemented in an array. 堆本身是在数组中实现的标准二进制堆。 The only difference is that every time you move an item from one place to another in the heap, you update its location in the dictionary. 唯一的区别是,每次将项目从堆中的一个位置移动到另一个位置时,都会更新其在字典中的位置。 So, for example, if you swap two items, you have to swap not only the items themselves in the array, but also their positions as stored in the dictionary. 因此,例如,如果交换两个项目,则不仅必须交换项目本身在数组中的位置,还必须交换它们在字典中存储的位置。 For example: 例如:

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
}

It's a pretty simple modification of a standard binary heap implementation. 这是对标准二进制堆实现的非常简单的修改。 You just have to be careful to update the position every time you move an item. 您只需要在每次移动项目小心更新位置即可。

You can also do this with node-based heaps like Pairing heap, Fibonacci heap, Skew heap, etc. 您还可以使用基于节点的堆(例如配对堆,斐波纳契堆,偏斜堆等)来执行此操作。

I think you're looking for an order statistics tree , an augmented BST that supports all the regular BST operations in time O(log n), along with two others: 我认为您正在寻找订单统计树 ,这是一种增强的BST,它支持时间为O(log n)的所有常规BST操作以及其他两个操作:

  • rank(elem): return which index elem would occupy in the sorted sequence. rank(elem):返回排序后的元素将占用的索引。
  • index(k): given an index k, return the element at that index in the sorted sequence. index(k):给定索引k,返回排序序列中该索引处的元素。

The two above operations run in O(log n) time, making them extremely fast. 以上两个操作的运行时间为O(log n),因此非常快。

You can treat an order statistics tree as a priority queue. 您可以将订单统计树视为优先级队列。 Insertions work as normal BST insertions, and to extract the lowest/highest element you just remove the smallest/greatest element from the tree, which you can do in time O(log n) by just walking down the left or right spines of the tree. 插入与普通的BST插入一样工作,要提取最低/最高元素,您只需从树中删除最小/最大元素,就可以在时间O(log n)中通过沿着树的左或右棘走而完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM