在优先级队列中随机访问
Randomly Access in a Priority Queue
如何在优先级队列中随机访问/搜索?。例如,如果有一个优先级队列,比如q={5,4,3,2,1},例如,我想直接访问第三个值,也就是3,我不能这样做,在优先级队列中有随机访问的过程吗?
大多数优先级队列实现,包括C++std::priority_queue
类型,都不支持随机访问。优先级队列背后的思想是牺牲随机访问来快速访问最小元素。
根据你想做的事情,你可以使用许多其他方法。如果总是想要访问队列中的第三个元素(而不是任何其他任意位置),那么只需将两个元素出列,缓存它们,然后将所需的值出列,并将其他两个元素放回就足够快了。
如果您想在任何时间点访问第k个最小的元素,其中k较大,一种选择是存储两个不同的优先级队列:一个包含k个元素的反向排序优先级队列(称为左队列)和一个包含其余n-k个元素(称为右队列)的常规优先级队列。要获得第k个最小元素,请从左队列出列(返回第k个最少元素),然后从右出列一个元素,并将其排入左队列,使其返回到总共k个元素。要进行排队,请检查该数字是否小于左侧队列的顶部。如果是,请从左侧队列出列,将删除的元素排入右侧队列,然后将原始元素排入左侧队列。否则,请向右排队。这保证了每个操作的运行时间为O(logn)。
如果您需要对排序序列进行真正的随机访问,请考虑使用顺序统计树。这是一个扩充的二进制搜索树,支持通过索引对元素进行O(logn)访问。您可以使用它来构建优先级队列-最小元素始终位于索引0处。问题是(当然也有问题)很难找到一个好的实现,并且隐藏在O(logn)项中的常数因子比标准二进制堆中的常数高得多。
添加到@templateypepedef的答案中:
除非使用效率非常低的优先级队列,否则不能将元素的随机访问与优先级队列相结合。根据您的需要,这里有几个选项:
1-一个低效的优先级队列将是一个保持排序的std::vector
。推动一个元素意味着找到它应该插入的位置,并向前移动所有后续元素。弹出一个元素将简单地读取和删除最后一个元素(back
和pop_back
,它们是有效的)。当然,随机访问也是有效的。
2-您可以使用std::multiset
(或std::multimap
)而不是优先级队列。它是一个保持事物有序的树状结构。您可以使用insert
而不是push
,然后使用带有erase
的begin
(或rbegin
)迭代器读取并删除第一个(或最后一个)元素。插入和查找第一个/最后一个元素是log(n)操作。数据结构允许按顺序读取所有元素,尽管它不提供随机访问。
3-你可以使用std::vector
、std::push_heap
和std::pop_heap
算法(以及std::vector
的push_back
和pop_back
方法)破解你自己版本的std::priority_queue
。您将获得同样高效的优先级队列,但也可以随机访问priority_queue的所有元素。它们没有排序,您只知道数组中的第一个元素是最高优先级的元素,其他元素以满足堆属性的方式存储。如果只是偶尔想按顺序读取所有元素,可以使用函数std::sort_heap
按优先级对数组中的所有元素进行排序。函数std::make_heap
会将数组返回到其堆状态。
注意,默认情况下,std::priority_queue
使用std::vector
来存储其数据。reinterpret_cast
、std::priority_queue
到std::vector
可能是可行的,因此您可以随机访问队列中的其他元素。但是,如果它适用于标准库的实现,那么它可能不适用于其他库,也不适用于同一库的未来版本,所以我不建议您这样做!按照上面的#3,使用标准库中的算法创建自己的堆类更安全。
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?
- 如何为我的容器实现随机访问迭代器?
- 对于C++随机访问迭代器(矢量迭代器),迭代器之间的差异是如何计算的?
- 对于随机访问迭代器(矢量迭代器),迭代器C++样式指针吗?
- Deque 中元素的随机访问如何提供恒定的时间复杂度?
- C++ STL 数据结构常时按索引推送/弹出/随机访问,并具有指向元素的可靠指针
- SFINAE - 检测类型 T 是指针、数组还是带有随机访问运算符的容器,以及给定的值类型
- 随机访问迭代器:我错过了什么?
- 随机访问元组向量中的元组值
- 有没有办法在C++中制作无锁"counter"随机访问迭代器?
- 当 95% 情况下的值为 0 或 1 时,对非常大的数组进行随机访问的任何优化
- 如何确保函数模板的参数是随机访问迭代器
- C++基于现有随机访问迭代器的反向迭代器
- C++ 写入随机访问文件
- 如何实现随机访问迭代器的"less than operator"?
- 随机访问迭代器和Deque
- 如何创建一个随机访问式的Rreference以访问.RC文件中定义的资源
- 在链表上实现随机访问迭代器
- 随机访问文件格式,用于分层组织的二进制文件和文本文件