C 中使用了哪种类型的堆以及STD :: Pirstity_queue的时间复杂性
What type of heap is used and time complexity of std::priority_queue in c++?
我想知道什么
我想询问以下两个问题。
- 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堆确实具有更好的分散性复杂性,但其恒定因素更大,因此您需要一个相对较大的图,以使其值得使用斐波那契堆代替二进制堆。这是一个常见的错误 - 更好的分解复杂性并不意味着算法优于>>>>>>>>>>输入的替代方案。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用一个考虑到std::map中键值的滚动或换行的键
- 如何从 std::atomic 中提取指针 T<T>?
- 为什么 std::unique 不调用 std::sort?
- 使用std::函数映射对象方法
- 可组合的lambda/std::函数与std::可选