Может быть, кто-нибудь проявит любезность и объяснит, как должен быть разработан метод "inserttionSort"?
Во-первых, я предлагаю избавиться от переменной length
или, по крайней мере, не использовать его в своей рутине.Это не нужно, и полагаться на это может отвлечь ваше мышление в сторону реализации в стиле массива.Вы знаете, что достигли конца списка, когда обнаружили узел, указатель next
которого равен NULL.
Во-вторых, я повторяю мой комментарий о том, что вы неправильно выполняете перестановки узлов для двусвязного списка.,Замена узла в любом связанном списке, независимо от того, является ли он одно- или двусвязным, эквивалентна извлечению второго узла из списка в целом, а затем повторной вставке его перед первым.В односвязном списке, который затрагивает, как правило, три узла: в дополнение к двум обмениваемым, предшественник к первому.В двусвязном списке это также влияет на преемника второго.Это достаточно запутанно в случае с двойной связью, и я предлагаю явно структурировать его как исключение с последующей вставкой.
Но я также предлагаю вам сделать шаг назад и посмотреть на алгоритм с высокого уровня.Он работает, рассматривая каждый узел по очереди, начиная со второго, и, если необходимо, удаляя его и вставляя его в правильную позицию в (отсортированном) подсписке, предшествующем ему.Так что же тогда с этим связано парным обменом? Nothing .Это деталь, удобная для реализации такой сортировки в массиве, но она делает ненужную работу при сортировке связанного списка.
Для связанного списка, особенно двусвязного, я предлагаю реализацию, которая более непосредственно относится кабстрактное описание алгоритма:
- Сохранение указателя
S
на последний узел отсортированного ведущего подсписка.Первоначально это будет указывать на заголовок списка. - Если
S
указывает на последний узел (который можно судить по S->next
), то остановитесь. - В противном случае проверьте,
*N
, преемник *S
, правильно упорядочен относительно * S. - Если это так, тогда установите
S
(указатель, а не его референт) равным N
. - Если нет, тогда
- вырежьте
*N
изсписок (обновляя как своего предшественника, так и его преемника, если таковой имеется, соответственно) и - шаг назад через отсортированный подсписок, пока вы не достигнете либо первого узла, либо узла, предшественник которого должен предшествовать
*N
, в зависимости от того, что встречаетсяfirst. - Вставьте
*N
перед узлом, который вы обнаружили. - Если это делает
*N
заголовком списка (о чем вы можете судить по новому значению указателя previous
), затем установите указатель головы (не его референт), равный N
.
- , повторите с точки 2
фактический код оставлен как упражнение, которому он предназначен.