Я думаю, что это связано с выбором точки разворота.В зависимости от того, как работает ваш шаг разбиения, если у вас много повторяющихся значений, ваш алгоритм может выродиться в квадратичное поведение при столкновении со многими дубликатами.Например, предположим, что вы пытаетесь выполнить быструю сортировку этого потока:
[0 0 0 0 0 0 0 0 0 0 0 0 0]
Если вы не будете осторожны с этапом разбиения, это может быстро ухудшиться.Например, предположим, что в качестве первого 0 вы выбираете сводную точку, оставляя массив с
[0 0 0 0 0 0 0 0 0 0 0 0]
для разбиения.Ваш алгоритм может сказать, что меньшие значения - это массив
[0 0 0 0 0 0 0 0 0 0 0 0]
А большие значения - это массив
[]
. Это тот случай, когда быстрая сортировка вырождается в O (n *).1013 * 2 ), так как каждый рекурсивный вызов только уменьшает размер ввода на единицу (а именно, вытягивая элемент pivot).
Я заметил, что в вашем коде ваш шаг разбиения делаетдействительно, сделайте это:
for items in array:
if items <= pivotVal:
smaller.append(items)
else:
greater.append(items)
Учитывая поток, который представляет собой целую кучу копий одного и того же элемента, он соберет их все в один массив для рекурсивной сортировки.
Конечно, этокажется смешным случаем - как это вообще связано с уменьшением количества значений в массиве?- но на самом деле это происходит, когда вы сортируете множество элементов, которые не различаются.В частности, после нескольких проходов разбиения вы, вероятно, сгруппируете все равные элементы, что приведет вас к этому делу.
Для обсуждения того, как этого избежать, есть действительноВеликий разговор Боба Седжвика и Джона Бентли о том, как изменить шаг разбиения для быстрой работы при наличии дублирующихся элементов.Она связана с проблемой Дейкстры с голландским национальным флагом , и ее решения действительно умны.
Один из вариантов, который работает, - это разделить входные данные на три группы - меньше, равно и больше.После того, как вы разбили входные данные таким образом, вам нужно отсортировать только меньшие и большие группы;равные группы уже отсортированы.Приведенная выше ссылка на доклад показывает, как сделать это более или менее на месте, но, поскольку вы уже используете быструю сортировку не на своем месте, исправить это будет легко.Вот моя попытка:
for items in array:
if items < pivotVal:
smaller.append(items)
elif items == pivotVal:
equal.append(items)
else:
greater.append(items)
Я никогда в жизни не писал ни одной строки Python, кстати, так что это может быть абсолютно недопустимым синтаксисом.Но я надеюсь, что идея ясна!: -)