Это, вероятно, приходит к вам немного поздно в игре, насколько ваш вопрос касается, но давайте быть полным.
Тестирование - лучший способ ответить на этот вопрос для вашей конкретной архитектуры, компилятора и реализации компьютера. Кроме того, существуют обобщения.
Прежде всего очереди приоритетов необязательно должны быть O (n log n).
Если у вас есть целочисленные данные, есть очереди приоритетов, которые работают в O (1) раз. Публикация Бюхера и Майера 1992 года «Морфологический подход к сегментации: преобразование водоразделов» описывает иерархические очереди, которые довольно быстро работают для целочисленных значений с ограниченным диапазоном. Издание Брауна 1988 года «Календарные очереди: быстрая реализация очереди 0 (1) для задачи набора симуляции» предлагает другое решение, которое хорошо сочетается с более широкими диапазонами целых чисел - два десятилетия работы после публикации Брауна дали хорошие результаты для выполнения целого числа приоритетные очереди fast. Но механизм этих очередей может усложниться: сортировка ведра и сортировка по методу рад может по-прежнему обеспечивать работу O (1). В некоторых случаях вы даже можете квантовать данные с плавающей запятой, чтобы воспользоваться приоритетной очередью O (1).
Даже в общем случае данных с плавающей запятой O (n log n) мало вводит в заблуждение.Книга Edelkamp в «Эвристический поиске: теория и приложение» имеет следующую удобную таблицу, показывающую временную сложность для различных алгоритмов очереди приоритетов (помните, что очереди приоритетов эквивалентны сортировки и управлению кучей):
Как вы можете во многих очередях приоритетов O (log n) стоит не только для вставки, но и для извлечения и даже управления очередью! Хотя коэффициент обычно снижается для измерения временной сложности алгоритма, эти затраты все еще стоит знать.
Но все эти очереди все еще имеют сложности времени, которые сопоставимы. Что лучше? В этом документе рассматривается статья 2010 года Криса Л. Луенго Хендрикса, озаглавленная «Пересмотр очередей приоритетов для анализа изображений».
В тесте удержания Hendriks', очередь приоритет был затравку N случайных чисел в диапазоне [0,50]. Верхний элемент очереди был затем удален, увеличен на случайное значение в диапазоне [0,2], а затем поставлен в очередь. Эта операция была повторена 10^7 раз. Накладные расходы на создание случайных чисел были вычтены из измеренных времен. Тесты лестниц и иерархические кучи выполнялись достаточно хорошо.
Время элемента для инициализации и опорожнения очередей также было измерено --- эти тесты очень актуальны для вашего вопроса.
Как вы можете видеть, различные очереди часто были очень разные ответы на enqueueing и освобождении пакета из очереди. Эти цифры подразумевают, что, хотя могут быть алгоритмы приоритетной очереди, которые являются превосходными для непрерывной работы, нет лучшего выбора алгоритма для простого заполнения и затем опорожнения очереди приоритетов (операция, которую вы выполняете).
Давайте оглянемся на вопросы:
Что быстрее: вставив в приоритетной очереди, или сортировка задним числом?
Как показано выше, очереди приоритетов могут быть эффективными, но по-прежнему существуют затраты на вставку, удаление и управление. Вставка в вектор выполняется быстро. Это O (1) в амортизированном времени, и нет затрат на управление, плюс вектор O (n) для чтения.
Сортировка вектора будет стоить вам O (n log n), если у вас есть данные с плавающей запятой, но на этот раз сложность не скрывала такие вещи, как очереди с приоритетом. (Тем не менее, вы должны быть немного осторожны. Quicksort очень хорошо работает с некоторыми данными, но имеет худшую временную сложность O (n^2). Для некоторых реализаций это серьезный риск для безопасности.)
Боюсь, у меня нет данных о стоимости сортировки, но я бы сказал, что ретроактивная сортировка отражает суть того, что вы пытаетесь сделать лучше, и, следовательно, лучший выбор. Исходя из относительной сложности управления очередью приоритетов и пост-сортировки, я бы сказал, что пост-сортировка должна быть быстрее. Но опять же, вы должны проверить это.
Я создаю некоторые предметы, которые мне нужно отсортировать в конце. Мне было интересно, что быстрее с точки зрения сложности: вставка их непосредственно в очередь приоритетов или аналогичную структуру данных или с помощью алгоритма сортировки в конце?
Возможно, мы покрыли это выше.
Есть еще один вопрос, который вы не задавали. И, возможно, вы уже знаете ответ. Речь идет о стабильности. C++ STL говорит, что очередь приоритетов должна поддерживать «строгий слабый» порядок. Это означает, что элементы равного приоритета несравнимы и могут быть размещены в любом порядке, а не в «общем порядке», где каждый элемент сопоставим. (Есть хорошее описание порядка here.) При сортировке «строгий слабый» аналогичен нестабильной сортировке, а «полный порядок» аналогичен устойчивому виду.
Результат состоит в том, что если элементы с одним и тем же приоритетом должны оставаться в том же порядке, что и вы вставляете их в свою структуру данных, вам нужен стабильный вид или полный порядок. Если вы планируете использовать C++ STL, у вас есть только один вариант. Приоритетные очереди используют строгий слабый порядок, поэтому они бесполезны здесь, но алгоритм «stable_sort» в библиотеке алгоритмов STL выполнит свою работу.
Надеюсь, это поможет. Дайте мне знать, если вы хотите получить копию любой из упомянутых статей или хотите получить разъяснения. :-)
любые сведения о количестве данных? вам нужна полная сортировка/стабильная сортировка или частичная сортировка/nth_element? – MadH
Мне нужен полный сорт, но он не должен быть стабильным. Меня больше интересует сложность, чем производительность для конкретного размера проблемы, поэтому я не указал ее. –
почти дубликат (но для Java, поэтому я не проголосовал за закрытие): http://stackoverflow.com/questions/3607593/is-it-faster-to-add-to-a-collection-then-sort- это или добавленная к сортировке коллекция – Thilo