В Cormen упоминаются два метода разбиения быстрой сортировки:
Hoare-Partition(A, p, r)
x = A[p]
i = p - 1
j = r + 1
while true
repeat
j = j - 1
until A[j] <= x
repeat
i = i + 1
until A[i] >= x
if i < j
swap( A[i], A[j] )
else
return j
а также:
Lomuto-Partition(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
swap( A[i], A[j] )
swap( A[i +1], A[r] )
return i + 1
Вне зависимости от метода выбора оси, в каких ситуациях одно предпочтительнее другого? Я знаю, например, что Lomuto сравнительно плохо преобразуется, когда высокий процент повторяющихся значений (т. Е. Где, скажем, более 2/3 массива - это одно и то же значение), где Hoare отлично работает в этой ситуации.
Какие другие особые случаи делают один метод разбиения значимым лучше, чем другой?
algorithms
sorting
quicksort
Роберт С. Барнс
источник
источник
A[i+1] <= x
. В отсортированном массиве (и с учетом разумно выбранных опорных точек) Хоар почти не меняет местами, а Ломуто делает тонну (как только j становится достаточно маленьким, тогда всеA[j] <= x
.) Чего мне не хватает?swap(A[p], A[j])
в конце Hoare, чтобы получить одинаковое поведение для обоих.i < j
в 2 повторных циклах разбиения Хоара.Ответы:
Педагогическое измерение
Из-за своей простоты метод разбиения Lomuto может быть проще в реализации. В « Жемчужине программирования» Джона Бентли о сортировке есть хороший анекдот :
Измерение производительности
Для практического использования простота реализации может быть принесена в жертву ради эффективности. Теоретически, мы можем определить количество сравнений элементов и обменов для сравнения производительности. Кроме того, на фактическое время работы будут влиять другие факторы, такие как производительность кэширования и неправильные прогнозы ветвлений.
Как показано ниже, алгоритмы ведут себя очень похоже на случайные перестановки, за исключением количества перестановок . Там Ломуто нужно в три раза больше, чем Хоаре!
Количество сравнений
Количество свопов
Количество перестановок является случайным для обоих алгоритмов, в зависимости от элементов в массиве. Если мы предполагаем случайные перестановки , то есть все элементы различны, и каждая перестановка элементов одинаково вероятна, мы можем проанализировать ожидаемое количество перестановок .
Метод Ломуто
Метод Хоара
Наконец, мы снова усредняем значения по всем опорным точкам, чтобы получить общее ожидаемое количество перестановок для разбиения Хоара:
(Более подробное описание можно найти в моей магистерской диссертации , стр. 29.)
Шаблон доступа к памяти
Оба алгоритма используют два указателя в массиве, которые сканируют его последовательно . Поэтому оба ведут себя почти оптимально по отношению к кешированию.
Равные элементы и уже отсортированные списки
Как уже упоминалось в Wandering Logic, производительность алгоритмов отличается более резко для списков, которые не являются случайными перестановками.
A[j] <= x
Заключение
Метод Ломуто прост и проще в реализации, но его не следует использовать для реализации метода сортировки библиотеки.
источник
Некоторые комментарии добавлены к отличному ответу Себастьяна.
Я собираюсь рассказать об алгоритме перестановок разделов в целом, а не о его конкретном использовании для быстрой сортировки .
стабильность
Алгоритм Ломуто полустабилен : сохраняется относительный порядок элементов, не удовлетворяющих предикату . Алгоритм Хоара нестабилен.
Шаблон доступа к элементу
Алгоритм Lomuto может использоваться с односвязным списком или аналогичными структурами данных только для пересылки. Алгоритм Хоара требует двунаправленности .
Количество сравнений
Но чтобы сделать это, мы должны пожертвовать 2 свойствами:
источник