Какой тип кучи используется и временная сложность очереди std::priority в c++? [дубликат]
этот вопрос уже есть ответ здесь:
- эффективность STL priority_queue 6 ответов
что я хочу знать
Я хочу спросить о следующих двух вопросах.
- какой тип кучи используется в std:: priority_queue в C++?
- что является ли сложность времени
top(), pop(), push()
операция для std:: priority_queue в C++?
Я проверил в интернете, но не смог найти ответа.
Пожалуйста, скажи мне ответ. Если вы не знаете всю версию на C++, пожалуйста, скажите мне этот ответ для GCC C++11 или C++14.
зачем мне нужен
Я хочу реализовать алгоритм Дейкстры для задачи кратчайшего пути.
пусть number of vertex = |V|, number of edge = |E|
в диаграмма.
Сложность времени O(|E| log |V|)
С помощью Двоичные Кучи.
но сложность времени 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;
}
};
EDIT: это не дубликат этот вопрос. Есть только временная сложность. Я также хочу знать, какой тип кучи используется. Пожалуйста, скажите мне просто.
2 ответов
в ответе @IvayloStrandjev уже упоминается, что стандарт C++ не требует конкретной реализации, а требует сложности времени. Таким образом, это зависит от реализации. Поскольку вы упомянули GCC в вопросе, я нашел эта документация GCC о реализации очереди приоритетов.
в основном он говорит, что несколько реализаций представлена:
- Куча Обрезки
- Бинарные Кучи
- Биномиальные Кучи
- RC Биномиальная куча
- Тонкий Кучи
и может быть настроен с помощью параметров тега. Тег по умолчанию для куча сопряжения. Поэтому я думаю, что это тот, который используется по умолчанию в GCC.
редактировать: как указал @MartinBonner в комментарии, ссылка предназначена для __gnu_pbds::priority_queue
вместо std::priority_queue
. Я скучал по этому раньше.
std::priority_queue
использует который в конечном итоге использует __push_метод кучи из bits / stl_heap.h. Быстрый взгляд на код выглядит как реализация Двоичные Кучи.
стандарт не указывает конкретную реализацию используемой кучи, а скорее определяет сложность ее операций и сложность памяти контейнера. Сложность операций заключается в следующем:--1-->
- top-O (1)
- pop-O (log (n))
- push-O (log (n))
- сложность памяти-O (n)
обратите внимание, что и Фибоначчи, и Th двоичная куча соответствуют этим требованиям. Однако от то, что я видел, обычно реализация двоичные кучи.
еще одно важное замечание-куча Фибоначчи имеет лучшую асимптотическую сложность, но ее постоянный фактор больше, поэтому вам нужен относительно большой график, чтобы сделать его стоящим использования кучи Фибоначчи вместо двоичной кучи. Это распространенная ошибка - лучше asympthotic сложности не означает, что алгоритм превосходит альтернативы любой вход.