Причина использования `std:: greater` для создания минимальной кучи через` priority_queue`

Мне интересно, почему для создания кучи min с помощью priority_queue следует использовать std::greater?

std::priority_queue<T, std::vector<T>, std::greater<T> > min_heap;

Для меня, поскольку наименьшее значение всегда находится в верхней части кучи, используемый класс должен быть std::less

Update: С другой стороны, поскольку поведение по умолчанию priority_queue (max heap) заключается в том, чтобы удерживать наибольшее значение вверху, мне кажется, что std::greater следует использовать для создания максимальной кучи, а не для создания минимальной кучи

Ответ 1

Логический аргумент выглядит следующим образом

  • std::priority_queue - контейнерный адаптер; основные соображения памяти делают заднюю часть предпочтительным местом для модификаций (с pop_back() и push_back()) для контейнеров последовательностей, таких как std::vector.
  • примитивы priority_queue основаны на std::make_heap (конструктор), std::pop_heap + container::pop_back (priority_queue::pop) и на container::push_back + std::push_heap (priority_queue::push)
  • pop_heap возьмет перед собой базовое хранилище и положит его обратно, после чего восстановит инвариант кучи. Обратное идет для push_heap.
  • Выполняя sort_heap на max_heap (сначала с max на фронте), снова выворачивает фронт назад > и сортирует диапазон в соответствии с less (который является оператором сравнения по умолчанию)
  • следовательно, предпочтительная реализация max_heap состоит в том, чтобы иметь максимальный элемент w.r.t. less спереди, доступ через priority_queue::top (ниже container::front).
  • можно по-прежнему обсуждать, является ли интуитивно понятным, что priority_queue с компаратором std::less представляет a max_heap. Его можно было бы определить как min_heap, изменив аргументы компаратора (но см. Комментарий от @T.C., Что с связями С++ 98 это довольно многословно) во всех случаях в вызовах различных функций кучи. Один (для меня) контр-интуитивный результат состоял бы в том, что top() не предоставил бы элемент с наивысшим приоритетом

Ответ 2

Функции кучи С++ make_heap, push_heap и pop_heap работают на max heap, то есть верхний элемент - это максимум при использовании компаратора по умолчанию. Итак, чтобы создать мини-кучу, вам нужно использовать greater<T> вместо less<T>.

Я подозреваю, что вместо кучи минимальной кучи используется максимальная куча, что ее легче реализовать с помощью операции less. В С++ less имеет специальную привилегию быть сортированным компаратором по умолчанию для всех алгоритмов STL; если вы собираетесь реализовать только одну операцию сравнения (кроме ==), она должна быть <. Это приводит к неудачной причуде, что priority_queue<T, C<T>, less<T>> означает max-queue, а priority_queue<T, C<T>, greater<T>> означает min-queue.

Кроме того, для некоторых алгоритмов, таких как nth_element, требуется максимальная куча.

Ответ 3

См. http://en.cppreference.com/w/cpp/container/priority_queue. A priority_queue предназначен для размещения наибольшего значения в верхней части. Это происходит, если вы используете компаратор по умолчанию std::less. Поэтому, если вам нужно обратное поведение, вам нужно использовать обратный компаратор, std::greater.