Быстрые алгоритмы сортировки
Альтернативный вариант quicksort
В дополнение к достаточно сложному для понимания алгоритму разбиения из прошлогодних материалов мы приведём более простую альтернативу
def partition(a, left, right):
pivot = a[left] ## или любой другой элемент массива
index = right-1 ## такой index работает только для a[left]
while left < right:
if a[left] < pivot: left += 1
else:
right -= 1
a[left], a[right] = a[right], a[left]
a[left], a[index] = a[index], a[left]
return left
def quicksort(array, left = 0, right = None):
if right == None: right = len(array)
if right - left <= 1: return
pivot_index = partition(array, left, right)
quicksort(array, left, pivot_index)
quicksort(array, pivot_index+1, right)
Корректность разбиения partition
здесь очевидна:
- элементы с индексами, меньшими
left
, всегда меньше опорного - элементы с индексами, не меньшими
right
, всегда не меньше опорного - за каждую итерацию цикла разница между
right
иleft
уменьшается на 1, поэтому цикл завершается, аright
не бывает меньшеleft
- отсюда, в частности, следует, что
right
иleft
в момент обмена находятся в пределах массива
На практике вышеприведённый алгоритм работает примерно на 10% медленнее, чем тот, который приведён в прошлогодних материалах (впрочем, в реальности в чистом виде quicksort редко используется — есть существенно более сложные, но при этом и более эффективные схемы сортировки).