STL priority_queue的效率

时间:2010-06-04 13:15:45

标签: c++ data-structures stl performance priority-queue

我有一个应用程序(C ++),我认为STL priority_queue可以很好地服务。 The documentation说:

  

Priority_queue是一个容器适配器,意味着它是在某个底层容器类型之上实现的。默认情况下,底层类型是vector,但可以显式选择其他类型。

  

优先级队列是一个标准概念,可以通过多种不同方式实现;这个实现使用堆。

我之前假设 top()O(1),而push()将是O(logn)(我选择{{}}的两个原因首先是{1}} - 但文档既没有证实也没有否定这种假设。

深入挖掘,序列概念的文档说:

  

单元素插入和擦除的复杂性依赖于序列。

priority_queue使用priority_queue(默认情况下)作为堆,其中:

  

...支持对元素的随机访问,最后元素的恒定时间插入和删除,以及在开头或中间插入和删除元素的线性时间。

我推断,使用默认vectorpriority_queuetop()O(1)push()

问题1:这是对的吗? (O(n)访问权限为top()O(1)push()?)

问题2:如果我使用O(n)(或O(logn))代替push(),我是否能够set效率multiset一个vector用于实施priority_queue?这样做的后果是什么?结果会有哪些其他行动受到影响?

N.B。:我担心时间效率,而不是空间。

6 个答案:

答案 0 :(得分:33)

优先级队列适配器使用标准库堆算法来构建和访问队列 - 这是您应该在文档中查找的那些算法的复杂性。

top()操作显然是O(1)但可能你想在调用它之后pop()堆(根据Josuttis)是O(2 * log(N))和push( )是O(log(N)) - 相同的来源。

从C ++标准,25.6.3.1,push_heap:

  

复杂性:至多是log(last-first)比较。

和pop_heap:

  

复杂性:最多2 * log(最后 - 第一)比较。

答案 1 :(得分:5)

没有。这是不正确的。 top()是O(1),push()是O(log n)。阅读文档中的注释2,看看此适配器不允许迭代向量。 Neil对于pop()是正确的,但是这仍然允许在O(log n)时间内使用堆进行插入和删除。

答案 2 :(得分:5)

top() - O(1) - 因为它只返回元素@ front。

push() -

  • 插入向量 - 0(1)摊销
  • push_into_heap - 最多是log(n)比较。 O(logn)时间

    所以push()的复杂性是 - LOG(n)的

答案 3 :(得分:2)

如果底层数据结构是堆,top()将是常量时间,push(EDIT:和pop)将是对数的(就像你说的那样)。向量仅用于存储以下内容:

HEAP:
 1
2个3
 8 12 11 9

VECTOR(用于存储)

1 2 3 8 12 11 9

您可以将其视为我孩子的位置元素是(2i)和(2i + 1)

他们使用向量,因为它按顺序存储数据(这比离散更有效且缓存友好)

无论它是如何存储的,都应该始终实现堆(尤其是制作STD lib的众神),以便pop是常量而push是对数的

答案 4 :(得分:2)

C ++ STL priority_queue底层数据结构是Heap数据结构(Heap是一个非线性ADT,它基于完整的二叉树,完整的二叉树是通过vector(或Array)容器实现的。

ex  Input data : 5 9 3 10 12 4.

Heap (Considering Min heap) would be :

                   [3]
             [9]             [4]
         [10]    [12]     [5]


   NOW , we store this min heap in to vector,             
      [3][9][4][10][12][5].
      Using formula ,
      Parent : ceiling of n-1/2
      Left Child : 2n+1
      Right Child : 2n+2 .
  Hence ,
    Time Complexity for 
             Top = O(1) , get element from root node.
             POP()= O(logn) , During deletion of root node ,there  is      chance to violation of  heap order . hence restructure of heap order takes at most O(logn) time (an element might move down to height of tree).
            PUSH()= O(logn) , During insertion also , there might chance to violation of  heap order . hence restructure of heap order takes at most O(logn) time (an element might move up to root from leaf node).

答案 5 :(得分:1)

问题1:我没有使用vector(或deque顺便说一句)查看标准,但AFAIK,O(1)的复杂度为top(),{ {1}}和O(log n) {1}}。我曾经将push()与我自己的堆与pop() std::priority_queue以及O(1)push() top()进行了比较,它肯定没有O(log n)那么慢{1}}。

Q2:pop()不能用作O(n)的基础容器(不是序列),但是可以使用set来实现set {{1的优先级队列}和priority_queue。但是,这可能不会超过O(log n)实施push()