Делаю Квиксорт для удовольствия, но есть что-то, чего я не понимаю
Просто хочу убедиться, что это не вопрос домашнего задания. Я делаю это просто для развлечения и, вероятно, для блога.
Я использую версию быстрой сортировки "на месте" в соответствии с этой Вики-страницей.
Вот код, который я написал:
# solution 2
def swap(arr, left, right):
try:
tmp = arr[left]
arr[left] = arr[right]
arr[right] = tmp
except IndexError:
print "!IndexError: left, right", left, right
raise
def partition(arr, left, right, pindex):
pivot = arr[pindex]
swap(arr, right, pindex)
npindex = left
for i in range(left, right+1): # +1 so the last item is included
if arr[i] < pivot:
swap(arr, i, npindex)
npindex += 1
swap(arr, npindex, right)
return npindex
def qs(arr):
qs2(arr, 0, len(arr)-1)
return arr
def qs2(arr, left, right):
if left < right:
# midpoint = (right - left) / 2
midpoint = left # this works.
nindex = partition(arr, left, right, midpoint)
qs2(arr, left, nindex-1)
qs2(arr, nindex+1, right)
def test():
test = [23, 45, 12, 1, 3, -9, 67, 122, 8, 2, 0]
res = qs(list(test))
print "startt", test
print "endt", res
if __name__ == "__main__":
test()
Чего я не понимаю, так это того, что, согласно Википедии, выбор pivot (variable midpoint inside function qs2) может быть случайным, пока он находится в пределах.
Однако, если я просто возьму среднюю точку (т. е. (левая + правая) /2 ), то quicksort не работает. Используя значение left , он работает.
Я что-то упустил в понимании алгоритма?
EDIT : я только что понял, что в stackoverflow есть тег 'quicksort'. Если этот вопрос был задан раньше, примите мои извинения и, пожалуйста, дайте мне знать. Я закрою этот вопрос. Тем временем я рассматриваю эти вопросы с помощью тега quicksort
2 ответа:
Выбор элемента pivot также осложняется наличием переполнения целых чисел. Если граничные индексы сортируемого подмножества достаточно велики, наивное выражение для среднего индекса (левый + правый)/2 вызовет переполнение и предоставит недопустимый индекс разворота. Это можно преодолеть, используя, например, left + (right-left)/2 для индексации среднего элемента, ценой более сложной арифметики. Аналогичные проблемы возникают и в некоторых других методах выбора точки разворота элемент.
Это должно быть
(left + right) / 2
, а не(right - left) / 2
. Википедия объясняет, что использованиеleft + (right - left) / 2
позволяет избежать переполнения целых чисел.