С самого начала: у вас есть два списка и новый заголовок списка, который вы будете возвращать.Изначально pnext указывает на это.
Код нацелен на то, чтобы сделать как можно меньше переназначений указателей, поэтому старается сохранить первоначальные «следующие» указатели входных списков без изменений.
list1 pnext->list->Null
|
V
o->o->o...
list2
|
V
o->o->o...
Swapчтобы гарантировать, что меньший элемент является первым из списка1.Эти строки делают:
Шаг за шагом:
*pnext = list1;
Получает * pnext (список перед первой итерацией), указывающий на узел, содержащий наименьший элемент:
list1
|
V
o->o->o...
^
|
list<-pnext
list2
|
V
o->o->o...
.
pnext = &list1->next;
Хитрая часть, как отмечалось ранее, & оператор имеет низкий приоритет.Также трудно отобразить графически, потому что это фактически смотрит на часть конструкции Node.Примерно так:
list1
|
V
o---->o->o...
^ ^
| |
list x<-pnext
list2
|
V
o->o->o...
, где x - следующий указатель на o, на который указывает list1.
list1 = *pnext;
Продвигает заголовок list1 по мере обработки его первого элемента.
list1<-pnext
|
V
o->o->o->...
^
|
list
list2
|
V
o->o->o->...
С этого момента у вас нет ничего общего со списком, поскольку вы хотите вернуть его в качестве заголовка объединенного списка.
Инвариант, в котором есть пустые точки, указывает на точку, где последний обработанныйследующий элемент указывает на то, куда должен идти самый маленький элемент из list1-2.Интересные вещи случаются со свопами, попробуйте сами отработать точную процедуру (трудно рисовать, как это, и хорошее упражнение, чтобы понять, что ** делает).Я мог бы добавить его, если найду хороший способ нарисовать его.
Вы не можете использовать list = list-> next;
, потому что он будет делать что-то вроде этого:
list1
|
V
o->o->o->...
^
|
list
list2
|
V
o->o->o->...
Что означает, что вы потеряете этот одинокий o(и все остальное, в конце концов, по мере выполнения цикла).
edit: *pnext = list2;
в конце делает это:
Завершение цикла (состояние перед указанным оператором):
list1<-pnext
|
V
o->o->o->null
^
|
list
o->o->o->...
^
|
list2
После оператора:
list1
|
V
o->o->o Null
^ |
| |
list |
V
o->o->o->...
^
|
list2<-pnext
Этот оператор добавляет оставшийся список в конец списка.Затем возвращается список узлов Node *, указывающий на начало объединенного списка.
edit2:
И все же, pnext будет лучше представлен следующим образом:
list1
|
V
o->o->o Null
^ |
| |<-pnext
list |
V
o->o->o->...
^
|
list2
Это означает, что он указывает на следующий указатель последнего обработанного узла.