Не правильно работает код на сортировку списка
Код:
a = [78, -32, 5, 39, 58, -5, -63, 57, 72, 9, 53, -1, 63, -97, -21, -94, -47, 57, -8, 60, -23, -72, -22, -79, 90, 96, -41, -71, -48, 84, 89, -96, 41, -16, 94, -60, -64, -39, 60, -14, -62, -19, -3, 32, 98, 14, 43, 3, -56, 71, -71, -67, 80, 27, 92, 92, -64, 0, -77, 2, -26, 41, 3, -31, 48, 39, 20, -30, 35, 32, -58, 2, 63, 64, 66, 62, 82, -62, 9, -52, 35, -61, 87, 78, 93, -42, 87, -72, -10, -36, 61, -16, 59, 59, 22, -24, -67, 76, -94, 59]
n = len(a)
for i in range(n-1):
a[i] , a[a.index(min(a[i:]))] = a[a.index(min(a[i:]))] , a[i]
print(*a)
Вывод:
78 -32 5 39 58 -5 -63 57 72 9 53 -1 63 -97 -21 41 -47 57 -8 60 -23 -72 -22 -79 90 96 -41 -71 -48 84 89 -96 -16 94 -60 -64 -39 60 -14 -62 -19 -3 32 98 14 43 3 -56 71 -71 -67 80 27 92 92 -64 0 -77 2 -26 41 3 -31 48 39 20 -30 35 32 -58 2 63 64 66 62 82 -62 9 -52 35 -61 87 78 93 -42 87 -72 -10 -36 61 -16 59 59 22 -24 -67 76 -94 -94 59
Как исправить, что бы сортировка работала корректно?
Ответы (2 шт):
Добавляю отладочную печать в ваш код:
def index(a, i):
j = a.index(min(a[i:]))
print('j', j)
return j
a = [78, -32, 5, 39, 58, -5, -63, 57, 72, 9, 53, -1, 63, -97, -21, -94, -47, 57, -8, 60, -23, -72, -22, -79, 90, 96, -41, -71, -48, 84, 89, -96, 41, -16, 94, -60, -64, -39, 60, -14, -62, -19, -3, 32, 98, 14, 43, 3, -56, 71, -71, -67, 80, 27, 92, 92, -64, 0, -77, 2, -26, 41, 3, -31, 48, 39, 20, -30, 35, 32, -58, 2, 63, 64, 66, 62, 82, -62, 9, -52, 35, -61, 87, 78, 93, -42, 87, -72, -10, -36, 61, -16, 59, 59, 22, -24, -67, 76, -94, 59]
n = len(a)
for i in range(n-1):
print('-')
print('i', i)
a[i] , a[index(a, i)] = a[index(a, i)] , a[i]
print(*a)
И получаю что значение j
меняется во время присваивания:
$ python sort.py - i 0 j 13 j 0 - ...
То есть перестановка элементов их не переставляет, а портит массив. Потому что оператор множественного присвоения компилируется так:
# a[i] , a[a.index(min(a[i:]))] = a[a.index(min(a[i:]))] , a[i]
# выражения справа сохраняются во временные переменные
temp_value1 = a[a.index(min(a[i:]))]
temp_value2 = a[i]
# значения из временный переменных сохраняются в выражения слева
a[i] = temp_value1
a[a.index(min(a[i:]))] = temp_value2
Присвоение в a[i]
меняет его значение и может изменить значение выражения a.index(min(a[i:]))
, что и видно в первой же перестановке.
Чинится фиксацией второго индекса j
:
j = a.index(min(a[i:]))
print(i, j, a[i], a[j])
a[i] , a[j] = a[j] , a[i]
В коде выше я добавил ещё отладочную печать, так как сортировка всё ещё не сортировка:
$ python sort.py 0 13 78 -97 1 31 -32 -96 2 15 5 -94 3 2 39 -94 ...
В последней строчке i = 3
, j = 2
. Индекс j
не должен быть меньше i
- минимум отыскивается в правой части списка. Но индекс минимума может найтись в левой, если в списке есть повторяющиеся значения. -94
- первое такое значение.
Ограничение на поиск индекса исправляет ситуацию:
j = a.index(min(a[i:]), i) # второй аргумент запрещает смотреть налево
assert i <= j # утверждение проверяет правильность j
a[i] , a[j] = a[j] , a[i]
Может я слабо разбираюсь в очень умных вещах... Я пытался понять идеологию этой борьбы с проблемой, честно пытался... Понять стиль такой фразы "код на сортировку списка", увы, мне было сложно. Однако, если вопрос о сортировке списка, значит, ответ в учебнике наверняка есть! Как Вам такое, Илон Маск:
a.sort()