C 中使用了哪种类型的堆以及STD :: Pirstity_queue的时间复杂性

What type of heap is used and time complexity of std::priority_queue in c++?

本文关键字:STD Pirstity 时间复杂性 queue 种类 类型      更新时间:2023-10-16

我想知道什么

我想询问以下两个问题。

  • C 中的STD :: Pirstity_que中使用了哪种类型的堆?
  • top(), pop(), push()操作的时间复杂性是什么是C ?

我在互联网上检查了,但找不到答案。
请告诉我答案。如果您不知道C 中的所有版本,请告诉我此答案的GCC C 11或C 14。

为什么我需要

我想实现Dijkstra的算法,以解决最短路径问题。

number of vertex = |V|, number of edge = |E|在图中。
时间复杂性是使用二进制堆的O(|E| log |V|)
但是时间复杂性是使用fibonacci堆的O(|E| + |V| log |V|)

,如您所见,如果图形密集的时间大不相同。
实际上,有O(|V|^2)算法而无需使用堆,所以我也想知道我是否必须实现它。

我的实施

这是我用二进制堆对优先级的实现。
insert(x)等于push(x)extract()等于top() --> pop()
但是STD :: Priority_queue比我的实现要快得多。

#include <vector>
#include <algorithm>
using namespace std;
template<class T> class PriorityQueue {
private:
    size_t size_; vector<T> heap;
public:
    PriorityQueue() : size_(1), heap(vector<T>(1, 0)) {};
    PriorityQueue(PriorityQueue& que) : size_(que.size_), heap(que.heap) {};
    size_t size() { return size_ - 1; }
    inline void insert(int x) {
        unsigned ptr = size_++; heap.push_back(x);
        while (ptr > 1) {
            if (heap[ptr >> 1] < heap[ptr]) swap(heap[ptr], heap[ptr >> 1]);
            ptr >>= 1;
        }
    }
    inline int extract() {
        int ret = heap[1]; unsigned ptr = 1;
        while ((ptr << 1) + 1 < size_) {
            ptr <<= 1;
            if (heap[ptr] > heap[ptr + 1]) swap(heap[ptr >> 1], heap[ptr]);
            else swap(heap[ptr + 1], heap[ptr >> 1]), ptr++;
        }
        heap[ptr] = heap[--size_], heap[size_] = 0;
        while (ptr > 1) {
            if (heap[ptr >> 1] < heap[ptr]) swap(heap[ptr], heap[ptr >> 1]);
            ptr >>= 1;
        }
        heap.pop_back();
        return ret;
    }
};

编辑:这不是这个问题的重复。只有时间复杂性。我也想知道使用了哪种类型的堆。请简单地告诉我。

@ivaylostrandjev的答案已经提到C 标准不需要特定的实现,而是需要时间复杂。因此,这取决于实施。由于您在问题中提到了GCC,因此我发现了有关实施优先队列的GCC的此文档。

基本上它说多个实现是呈现的:

  • paring堆
  • 二进制堆
  • 二项式堆
  • RC二项式堆
  • 薄堆

可以通过标记参数配置使用的一个。默认标签适用于配对堆。所以我想这是GCC中默认使用的。

edit :@martinbonner在注释中指向,该链接用于__gnu_pbds::priority_queue而不是std::priority_queue。我以前错过了。

std::priority_queue使用 make_heap函数,该功能最终从bits/stl_heap.h使用__push_heap方法。快速浏览代码看起来像是二进制堆的实现。

标准未指定所使用的堆的具体实现,而是指定其操作的复杂性和容器的内存复杂性。操作的复杂性如下:

  • top -o(1)
  • pop -o(log(n))
  • push -o(log(n))
  • 内存复杂性 - o(n)

请注意,斐波那契和二进制堆都符合这些要求。但是,从我看来,通常实现是二进制堆。

一个更重要的备注-Fibonacci堆确实具有更好的分散性复杂性,但其恒定因素更大,因此您需要一个相对较大的图,以使其值得使用斐波那契堆代替二进制堆。这是一个常见的错误 - 更好的分解复杂性并不意味着算法优于>>>>>>>>>>输入的替代方案。