STLpriority_queue的效率
我有一个应用程序 (C++),我认为 STL priority_queue
可以很好地服务该应用程序。 文档说:
Priority_queue 是一个容器适配器,这意味着它是在某些底层容器类型之上实现的。默认情况下,基础类型是向量,但可以显式选择不同的类型。
和
优先级队列是一个标准概念,可以通过多种不同方式实现;此实现使用堆。
我之前假设 top()
是 O(1)
,并且 push()
将是O(logn)
(我首先选择 priority_queue
的两个原因) - 但文档既没有证实也没有否认这个假设。
更深入地挖掘,序列概念的文档说:
单元素插入和擦除的复杂性取决于序列。
priority_queue
使用vector
(默认情况下)作为堆,其中:
...支持随机访问元素、末尾固定时间插入和删除元素、开头或中间线性时间插入和删除元素。
我推断,使用默认的 priority_queue
,top()
是 O(1)
和 push()
> 是O(n)
。
问题 1:这是否正确? (top()
访问是 O(1)
,push()
是 O(n)
?)
< strong>问题 2:如果我使用 set
,我能否在 push()
上实现 O(logn)
效率(或multiset
)而不是vector
来实现priority_queue
?这样做会产生什么后果?其他哪些操作会因此受到影响?
注意:我担心的是时间效率,而不是空间。
I have an application (C++) that I think would be well served by an STL priority_queue
. The documentation says:
Priority_queue is a container adaptor, meaning that it is implemented on top of some underlying container type. By default that underlying type is vector, but a different type may be selected explicitly.
and
Priority queues are a standard concept, and can be implemented in many different ways; this implementation uses heaps.
I had previously assumed that top()
is O(1)
, and that push()
would be a O(logn)
(the two reasons I chose the priority_queue
in the first place) - but the documentation neither confirms nor denies this assumption.
Digging deeper, the docs for the Sequence concept say:
The complexities of single-element insert and erase are sequence dependent.
The priority_queue
uses a vector
(by default) as a heap, which:
... supports random access to elements, constant time insertion and removal of elements at the end, and linear time insertion and removal of elements at the beginning or in the middle.
I'm inferring that, using the default priority_queue
, top()
is O(1)
and push()
is O(n)
.
Question 1: Is this correct? (top()
access is O(1)
and push()
is O(n)
?)
Question 2: Would I be able to achieve O(logn)
efficiency on push()
if I used a set
(or multiset
) instead of a vector
for the implementation of the priority_queue
? What would the consequences be of doing this? What other operations would suffer as a consequence?
N.B.: I'm worried about time efficiency here, not space.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
优先级队列适配器使用标准库堆算法来构建和访问队列 - 您应该在文档中查找这些算法的复杂性。
top() 操作显然是 O(1) 但大概你想在调用它之后 pop() 堆(根据 Josuttis) 是 O(2*log(N)) ,push() 是 O(log(N)) - 相同的来源。
来自 C++ 标准 25.6.3.1,push_heap :
和 pop_heap:
The priority queue adaptor uses the standard library heap algorithms to build and access the queue - it's the complexity of those algorithms you should be looking up in the documentation.
The top() operation is obviously O(1) but presumably you want to pop() the heap after calling it which (according to Josuttis) is O(2*log(N)) and push() is O(log(N)) - same source.
And from the C++ Standard, 25.6.3.1, push_heap :
and pop_heap:
top()
- O(1) - 因为它只返回元素@ front。push()
-push_into_heap - 最多 log(n) 次比较。 O(logn)
所以push()的复杂度是——
log(n)
top()
- O(1) -- as it just returns the element @ front.push()
-push_into_heap - At most, log(n) comparisons. O(logn)
so push() complexity is --
log(n)
不,这是不正确的。 top() 的复杂度为 O(1),push() 的复杂度为 O(log n)。请阅读文档中的注释 2,了解该适配器不允许迭代向量。 Neil 关于 pop() 的说法是正确的,但这仍然允许在 O(log n) 时间内使用堆进行插入和删除操作。
No. This is not correct. top() is O(1) and push() is O(log n). Read note 2 in the documentation to see that this adapter does not allow iterating through the vector. Neil is correct about pop(), but still this allows working with the heap doing insertions and removals in O(log n) time.
如果底层数据结构是堆,top()将是常数时间,而push(编辑:和pop)将是对数的(就像你说的)。向量只是用来存储这些东西,如下所示:
HEAP:
1
2 3
8 12 11 9
VECTOR (用于存储)
1 2 3 8 12 11 9
你可以将其视为位置 i 的子元素的元素是 (2i) 和 (2i+1)
他们使用向量是因为它顺序存储数据(这比离散的效率高得多,而且对缓存友好)
无论如何存储,都应该始终实现堆(尤其是制作 STD lib 的大神们),这样 pop 是恒定的,push 是对数的
If the underlying data structure is a heap, top() will be constant time, and push (EDIT: and pop) will be logarithmic (like you are saying). The vector is just used to store these things like this:
HEAP:
1
2 3
8 12 11 9
VECTOR (used to store)
1 2 3 8 12 11 9
You can think of it as the element at position i's children is (2i) and (2i+1)
They use the vector because it stores the data sequentially (which is much more efficient and cache-friendly than discrete)
Regardless of how it is stored, a heap should always be implemented (especially by the gods who made the STD lib) so that pop is constant and push is logarithmic
C++ STL的priority_queue底层数据结构是堆数据结构(堆是一种基于完全二叉树的非线性ADT,完全二叉树是通过向量(或数组)容器实现的。
C++ STL priority_queue underlying data structure is Heap data structure(Heap is a non linear ADT which based on complete binary tree and complete binary tree is implemented through vector(or Array) container.
Q1:我没有查看标准,但据我所知,使用
vector
(或deque
顺便说一句),复杂度将是O(1)
对于top()
,O(log n)
对于push()
和pop()
。我曾经使用O(1)
push()
和top()
将std::priority_queue
与我自己的堆进行比较> 和O(log n)
pop()
并且它肯定没有O(n)
慢。Q2:
set
不能用作priority_queue
的底层容器(不是序列),但可以使用 set 来实现优先级队列O( log n)
push()
和pop()
。但是,与std::vector
实现相比,这可能不会优于std::priority_queue
。Q1: I didn't look in the standard, but AFAIK, using
vector
(ordeque
btw), the complexity would beO(1)
fortop()
,O(log n)
forpush()
andpop()
. I once comparedstd::priority_queue
with my own heap withO(1)
push()
andtop()
andO(log n)
pop()
and it certainly wasn't as slow asO(n)
.Q2:
set
is not usable as underlying container forpriority_queue
(not a Sequence), but it would be possible to use set to implement a priority queue withO(log n)
push()
andpop()
. However, this wouldn't probably outperform thestd::priority_queue
overstd::vector
implementation.