Код неверен: есть некоторая путаница в значениях индекса и границах среза, а также в других ошибках:
индексы массива начинаются с 0
в python, поэтому вы должны вызвать Merge_sort(ar, 0, n)
длина среза n1
отключена на единицу, она должна быть n1 = q - p
тест на рекурсию должен вычислять длину среза и повторяться только для срезов как минимум с 2 элементами.
цикл слияния неверен: вы должны проверить, находятся ли i
и j
внутри срезов. Эффективный способ сделать это - заменить сравнение следующим тестом:
if i < n1 and (j == n2 or L[i] <= M[j]):
цикл слияния должен повторяться для k
с p
до r
исключено, а не с 0
до r
исключено
код приращения для j
выровнен неверно, необходимо сделать отступ еще на один шаг
Гораздо проще считать первый индекс включенным, а второй - исключенным. В сети слишком много учебников на разных языках, которые настаивают на других соглашениях, что неизменно вызывает замешательство у начинающих программистов.
Вот исправленная и упрощенная версия:
def Merge(arr, p, q, r):
n1 = q - p
n2 = r - q
L = arr[p : q]
M = arr[q : r]
i = 0
j = 0
for k in range(p, r):
if i < n1 and (j == n2 or L[i] <= M[j]):
arr[k] = L[i]
i = i + 1
else:
arr[k] = M[j]
j = j + 1
def Merge_Sort(arr, p, r):
if r - p >= 2:
q = (p + r) // 2
Merge_Sort(arr, p, q)
Merge_Sort(arr, q, r)
Merge(arr, p, q, r)
ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)
Обратите внимание, что вы можете еще больше упростить функцию MergeSort
с помощью одного временного массива, если убедитесь, что левый срез всегда по крайней мере такой же, как правый срез:
def Merge(arr, p, q, r):
tmp = arr[p : q]
i = 0
n = q - p
while i < n:
if q == r or tmp[i] <= arr[q]:
arr[p] = tmp[i]
i += 1
p += 1
else:
arr[p] = arr[q]
q += 1
p += 1
def Merge_Sort(arr, p, r):
if r - p >= 2:
q = (p + r + 1) // 2
Merge_Sort(arr, p, q)
Merge_Sort(arr, q, r)
Merge(arr, p, q, r)
ar = [5, 3, 6, 1, 2, 9, 7, 8]
Merge_Sort(ar, 0, len(ar))
print(ar)