Худший случай для QuickSort — когда это может произойти?

При анализе QS все всегда ссылаются на «почти отсортированный» наихудший случай. Когда такой сценарий может произойти с естественным входом?

Единственный пример, который я придумал, — это переиндексация.


person Community    schedule 10.03.2010    source источник
comment
Когда он уже отсортирован.   -  person YOU    schedule 10.03.2010
comment
это не совсем правильно, см. ответ Йенса   -  person swegi    schedule 10.03.2010
comment
@Shira, один из примеров почти отсортированных естественных данных - это моделирование движущихся объектов. Допустим, у вас есть несколько мячей, на которые действует гравитация и другие силы. Вы берете временной шаг и сортируете их по оси X. Теперь еще раз переместите временной шаг. Теперь эти данные почти отсортированы. Некоторые шары могли поменяться местами вдоль оси X за это короткое время, но большинство из них все еще отсортированы.   -  person mmcdole    schedule 10.03.2010
comment
Или даже любая ситуация, когда у вас есть данные, которые вы время от времени изменяете и время от времени сортируете. Это вовсе не редкость, особенно в таких языках, как Python и JS, где тип массива чрезвычайно широко используется и имеет быструю операцию сортировки на месте, а стандартный тип дерева отсутствует. (По-другому можно сказать, что переиндексация — чрезвычайно общая операция, которую многие программы выполняют в той или иной форме.)   -  person Jason Orendorff    schedule 10.03.2010


Ответы (6)


Я думаю, что люди путают Quicksort с алгоритмом сортировки на основе разделов и «qsort» с различными реализациями библиотек.

Я предпочитаю рассматривать алгоритм быстрой сортировки как имеющий подключаемый алгоритм выбора сводной точки, что очень важно при анализе его поведения.

Если первый элемент всегда выбирается в качестве опорного, то уже отсортированный список является наихудшим случаем. Часто существует высокая вероятность того, что массив уже/почти отсортирован, поэтому эта реализация довольно плохая.

Аналогично, выбор последнего элемента в качестве опорного не годится по той же причине.

Некоторые реализации пытаются избежать этой проблемы, выбирая средний элемент в качестве опорного. Это не будет так плохо работать с уже/почти отсортированными массивами, но все же можно создать ввод, который будет использовать этот предсказуемый выбор сводной точки и заставить его работать за квадратичное время.

Таким образом, вы получаете рандомизированные алгоритмы выбора пивота, но даже это не гарантирует O(N log N).

Поэтому были разработаны другие алгоритмы, которые использовали некоторую информацию из последовательности перед выбором точки разворота. Конечно, вы можете просмотреть всю последовательность, найти медиану и использовать ее в качестве точки опоры. Это гарантирует O(N log N), но на практике, конечно, медленнее.

Так что некоторые углы срезаны, и люди разработали алгоритм медианы 3. Конечно, позже даже это было использовано так называемым медианным из 3 «убийц».

Таким образом, предпринимается все больше попыток придумать более «интеллектуальные» алгоритмы выбора поворота, которые гарантируют O(N log N) асимптотическое поведение, которое все же достаточно быстро, чтобы быть практичным, с разной степенью успеха.

Так что на самом деле, если не указать конкретную реализацию быстрой сортировки, вопрос о том, когда возникает наихудший сценарий, плохо определен. Если вы используете так называемый алгоритм выбора разворота по медиане медиан, не существует квадратичного сценария наихудшего случая.

Однако большинство реализаций библиотек, вероятно, лишаются O(N log N) гарантии гораздо более быстрой сортировки в среднем случае. Некоторые из действительно старых реализаций используют первый элемент в качестве опорного элемента, который теперь хорошо известен как плохой и больше не является широко используемой практикой.

person polygenelubricants    schedule 10.03.2010
comment
Ни один алгоритм выбора опорной точки не может гарантировать O(N.log(N)) времени обработки. Это явно неправильно. Просто подумайте о тривиальном случае, когда все записи имеют одно и то же значение. - person Erwan Legrand; 14.03.2014
comment
@ErwanLegrand Этот тривиальный случай легко обойти для любого метода выбора опорной точки путем незначительного изменения алгоритма. Просто разделите на 3 набора: Меньше, Равно, Больше. т.е. QSort(List) { (Choose Pivot) Partition(List, Pivot, Less, Equal, Greater); return QSort(Less) + Equal + QSort(Greater); } По сути, нет смысла повторно сортировать элементы, равные сводной, потому что вы точно знаете, где они должны находиться в конечном результате. Оказывается, при таком подходе, если все записи имеют одинаковое значение, производительность будет O(n). - person Disillusioned; 11.07.2014

Я считаю, что наихудший случай для быстрой сортировки зависит от выбора опорного элемента на каждом шаге. Быстрая сортировка имеет наихудшую производительность, если сводная точка может быть либо самым маленьким, либо самым большим элементом в списке (например, первым или последним элементом уже отсортированного списка).

Если, например. вы выбираете средний элемент списка, уже отсортированный список не имеет наихудшего времени выполнения.

Таким образом, если вы подозреваете, что ваш сценарий, вероятно, является плохим сценарием для быстрой сортировки, вы можете просто изменить свой выбор элемента поворота, чтобы быстрая сортировка работала лучше.

Примечание. Я знаю, что это не дало больше примеров реальных случаев для наихудших случаев быстрой сортировки. Примеры этого зависят от реализации, с которой вы работаете.

person Jens    schedule 10.03.2010
comment
или вы используете что-то вроде медианы 3, чтобы получить относительно хорошо выбранную опорную точку - person swegi; 10.03.2010
comment
или вы используете случайный элемент. Это происходит только с очень (очень) малой вероятностью, независимо от возможно неясных входных данных. - person Jens; 10.03.2010
comment
Уже отсортированный мем, возможно, настолько распространен, потому что многие люди принимают первый элемент за точку опоры, предполагая, что список не отсортирован. В случае отсортированного списка это худший элемент, который вы можете выбрать. - person Frank Shearar; 10.03.2010
comment
Список в обратном порядке будет худшим случаем, если вы выберете первый элемент в качестве опорного. Нужно выбрать последний элемент, чтобы сделать уже отсортированный случай наихудшим. Примечание. Спрашивающий запрашивает почти отсортированный случай, который является наихудшим случаем только с высокой вероятностью, даже если вы выберете последний элемент. Может быть (с небольшой вероятностью), что медиана является последним элементом, что означает, что почти отсортированный также может быть лучшим случаем. - person swegi; 10.03.2010
comment
@swegi: проблема возникает, когда текущий подмассив недостаточно равномерно разделен для рекурсии. Неважно, какой из крайних (наибольшей или наименьшей) опорной точки выбран; пока это экстремально, вы получаете худшее поведение. - person Svante; 10.03.2010
comment
@Svante: Вы совершенно правы, спасибо, что указали на это. - person swegi; 10.03.2010
comment
Наихудший случай также может быть вызван повторяющимися элементами в зависимости от реализации быстрой сортировки. Если быстрая сортировка разбивается на [ ‹ p | ›= p] на каждом шаге, то наличие одинаковых элементов приведет к наихудшему поведению независимо от того, какой опорный элемент выбран, потому что один раздел [ ‹ p] каждый раз будет иметь нулевые элементы. Быстрая сортировка, которая разбивается на [ ‹= p | ›= p] также будет иметь. Существуют модификации этих быстрых сортировок, которые преодолевают эту трудность. - person Justin Peel; 10.03.2010
comment
Я думаю, что недостаточно хорошо сформулировал свой вопрос. Я не хотел спрашивать, какой ввод является наихудшим случаем для QS. Я предполагаю, что это почти отсортированный случай, и вопрос в том, когда мы получаем почти отсортированный ввод в реальных ситуациях ввода? Извините за сумбурность и спасибо за ответы :) - person ; 10.03.2010
comment
@JustinPeel Правильно, и модификация, которую вы ищете, это раздел [‹p | =р | >п]. В конце концов, очевидно, что все элементы с равенством p принадлежат между разделами ‹ и ›. Так что нет никакого смысла помещать их обратно в любой из разделов, чтобы пройти дальнейшие итерации сортировки. Также интересно отметить, что эта модификация делает все элементы равными в лучшем случае, позволяя выполнять сортировку со сложностью O(n) — также независимо от того, какой поворот выбран. - person Disillusioned; 11.07.2014

Фактический вопрос заключался в следующем: когда такой сценарий (почти отсортированный) может произойти с естественным входом?

Хотя все ответы касаются того, что вызывает наихудшую производительность, ни один из них не охватывает данные о том, что приводит к наихудшему сценарию производительности.

Итак, чтобы ответить на актуальный вопрос

  • Ошибка программиста: обычно вы дважды сортируете список. Обычно это происходит из-за того, что список отсортирован по одному месту в коде. А позже в другом фрагменте кода вы знаете, что вам нужно отсортировать список, поэтому вы сортируете его снова.

  • Использование почти хронологических данных. У вас есть данные, которые обычно поступают в хронологическом порядке, но иногда некоторые элементы находятся не на своем месте. (Рассмотрите многопоточную среду, добавляющую в список элементы с отметками времени. Условия гонки могут привести к тому, что элементы будут добавляться в порядке, отличном от того, в котором они были проставлены отметками времени.) В этой ситуации, если вам нужны отсортированные данные, вы должны повторно -Сортировать. Потому что порядок данных не гарантируется.

  • Добавление элементов в список: если у вас есть отсортированный список и вы просто добавляете некоторые элементы (т. е. без использования двоичной вставки). Вам нужно будет пересортировать почти отсортированный список.

  • Данные из внешнего источника. Если вы получаете данные из внешнего источника, может не быть гарантии их сортировки. Так что сортируй сам. Однако, если внешний источник отсортирован, вам придется пересортировать данные.

  • Естественный порядок: он аналогичен хронологическим данным. По сути, естественный порядок получаемых вами данных может быть отсортирован. Рассмотрим страховую компанию, добавляющую регистрацию автомобилей. Если орган, выдающий регистрацию автомобилей, делает это в предсказуемом порядке, более новые автомобили, скорее всего, но не гарантируют, будут иметь более высокие регистрационные номера. Поскольку вам не гарантируется, что он отсортирован, вам придется пересортировать.

  • Перемежающиеся данные. Если вы получаете данные из нескольких отсортированных источников с перекрывающимися ключами, вы можете получить ключи, похожие на следующие: 1 3 2 5 4 7 6 9 8 11 10 13 12 15 14 17 16 19 18. Несмотря на то, что половина элементов не соответствует порядку своих соседей, список почти отсортирован. Конечно, использование быстрой сортировки с опорой на первый элемент показало бы O(n^2) производительность.

Вывод

Итак, учитывая все вышеперечисленные сценарии, на самом деле довольно легко приступить к сортировке почти отсортированных данных. И именно поэтому QuickSort, который вращается на первом элементе, на самом деле лучше избегать. polygene предоставил некоторую интересную информацию об альтернативных вариантах поворота.

В качестве примечания: один из обычно худших алгоритмов сортировки, на самом деле неплохо справляется с почти отсортированными данными. В приведенных выше данных с чередованием для пузырьковой сортировки требуется всего 9 операций подкачки. Его производительность на самом деле будет O(n).

person Disillusioned    schedule 11.07.2014

Из быстрой сортировки

для быстрой сортировки «худший случай» соответствует уже отсортированному

Список, в котором все элементы имеют одинаковые номера, уже отсортирован.

person Adriaan Stander    schedule 10.03.2010
comment
очень плохо, но ваш источник не совсем прав, см. ответ Йенса - person swegi; 10.03.2010
comment
+1, поскольку, если все числа одинаковы, вы получите наихудший случай независимо от того, как вы выберете опорную точку. - person orip; 12.05.2010

худший случай в быстрой сортировке:

  1. Все элементы массива одинаковы
  2. Массив уже отсортирован в том же порядке
  3. Массив уже отсортирован в обратном порядке.
person Abhishek kumar yadav    schedule 28.05.2013

Быстрый худший случай зависит от выбора опорного элемента. поэтому проблема возникает только тогда, когда 1) массив уже отсортирован в том же порядке. 2) Массив уже отсортирован в обратном порядке. 3) Все элементы одинаковы (частный случай 1 и 2)

person Ankit jain    schedule 13.05.2016