Какой тип кучи используется и временная сложность очереди std::priority в c++? [дубликат]

этот вопрос уже есть ответ здесь:

что я хочу знать

Я хочу спросить о следующих двух вопросах.

  • какой тип кучи используется в 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 сложности не означает, что алгоритм превосходит альтернативы любой вход.