为什么优先级队列是使用堆实现的,当我们可以更有效地使用向量实现它时

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么优先级队列是使用堆实现的,当我们可以更有效地使用向量实现它时相关的知识,希望对你有一定的参考价值。

为什么priority_queue在没有使用堆的情况下使用堆实现,我们可以只用向量来实现它。

假设我们使用vector作为队列并按顺序保持元素。我们可以将其用作优先级队列。

插入:我们可以使用二进制搜索。 Complexity O(logN)

删除:这里我们也可以使用二进制搜索。 Complexity O(logN)

顶级元素:O(1)

另外,我们可以在O(1)时间访问第k个最大元素,而不是堆的情况。

那么,为什么我们使用堆来实现优先级队列呢?

答案

插入:我们可以使用二进制搜索。复杂度O(logN)

对于detion:这里我们也可以使用二进制搜索。复杂度O(logN)

不,你不能。通过使用排序的数组/向量,您只能在O(log N)上搜索正确的索引,但要进行实际的插入或删除,您必须移动其他元素,即O(N)

另一答案

默认优先级队列确实使用std::vector。它将堆算法分层,以获得所需的性能特征。

草图实现:

template <typename T>
class priority_queue
{
    std::vector<T> elems;
public:
    std::vector<T>::const_reference top() const { 
         return elems.front(); // O(1)
    }
    void push( const T& value ) { 
         elems.push_back(value); // Amortized O(1)
         std::push_heap(elems.begin(), elems.end()); // O(logN)
    }
    void pop() {
         std::pop_heap(elems.begin(), elems.end());  // O(logN)
         elems.pop_back(); // O(1)
    }
}

与你的建议比较

template <typename T>
class priority_queue
{
    std::vector<T> elems;
public:
    std::vector<T>::const_reference top() const { 
         return elems.back(); // O(1)
    }
    void push( const T& value ) { 
         std::vector<T>::iterator pos = std::lower_bound(elems.begin(), elems.end(), std::greater<>{}); // O(logN)
         elems.insert(pos, value); // O(N)
    }
    void pop() {
         elems.pop_back(); // O(1)
    }
}

以上是关于为什么优先级队列是使用堆实现的,当我们可以更有效地使用向量实现它时的主要内容,如果未能解决你的问题,请参考以下文章

什么是堆排序和优先队列? [关闭]

堆(Heap)和有优先队列(Priority Queue)

优先队列

10堆左倾堆

堆和优先级队列2:java实现堆和优先级队列

❤️值得收藏❤️优先级队列(堆)❤️全面讲解(易理解+附大量图+超详细)!!!