【发布时间】:2017-05-05 09:31:28
【问题描述】:
我想知道什么
我想问以下两个问题。
- 在 C++ 中的 std::priority_queue 中使用什么类型的堆?
- C++ 中 std::priority_queue 的
top(), pop(), push()操作的时间复杂度是多少?
我上网查了一下,没找到答案。
请告诉我答案。如果您不知道 C++ 的所有版本,请告诉我这个 GCC C++11 或 C++14 的答案。
我为什么需要
我想针对最短路径问题实施Dijkstra's Algorithm。
让number of vertex = |V|, number of edge = |E|在图中。
时间复杂度为O(|E| log |V|),使用Binary Heap。
但时间复杂度为O(|E| + |V| log |V|),使用Fibonacci Heap。
如您所见,如果图形密集,时间会非常不同。
其实有O(|V|^2)算法不使用堆,所以我也想知道是否必须实现。
我的实现
这是我使用Binary Heap 实现的优先级队列。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;
}
};
编辑:这不是 this question 的重复。只有时间复杂度。我也想知道使用的是什么类型的堆。请简单告诉我。
【问题讨论】:
-
top 和 pop 具有恒定的复杂度,而 push 具有对数复杂度。 C++ 标准没有指定应该使用什么 type 堆。它只是指定实现必须遵守的目标复杂性。
-
@ilim 没有关于什么类型的堆(例如二进制堆/斐波那契堆)的信息,所以它不是重复的。
-
@square1001 但是 std::priority_queue 比我的实现要快得多。 -- 只需查看头文件即可获得源代码。
-
@ArmenTsirunyan pop 不是恒定的
-
二进制堆和斐波那契堆之间有什么区别(操作的时间复杂度)?如果你能回答这个问题,你可以看到 C++ 标准的要求(它可能允许任何一个),如果你不能回答这个问题 - 你为什么在乎?
标签: c++ algorithm c++11 priority-queue dijkstra