Возможно, некоторые изображения помогут.
Перед вызовом insertNode
у вас есть последовательность узлов, связанных так:
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
У вас есть указатель (назовите его h
), который указывает на первый элемент списка:
+---+
| h |
+---+
|
V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Когда вы вызываете insertNode
, вы передаете указатель на h
в качестве параметра, который мы называем head
:
+------+
| head |
+------+
|
V
+---+
| h |
+---+
|
V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Вы создаете переменную-указатель с именем ref
, которая принимает значение *head
(h
);IOW, ref
указывает на первый элемент списка:
+------+ +-----+
| head | | ref |
+------+ +-----+
| |
V |
+---+ |
| h | |
+---+ |
| +----+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Затем вы создаете другой узел в куче и присваиваете этот указатель локальной переменной с именем new
:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Итак, следует отметить, что хотя ref
и *head
(h
) имеют одинаковое значение (адрес первого узла в списке), ониэто разные объекты.Таким образом, все, что изменяет значение ref
, не влияет ни на head
, ни на h
.
Итак, если мы выполним этот цикл
while(ref->next != null) {
ref = ref->next;
, результат первой итерации будет
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
После другой итерации мы получим
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next |
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----------------------------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
В этот момент ref->next
равно NULL
, поэтому цикл завершается.
Затем мы присваиваем значения new->value
и new->next
, так что new->next
равно NULL
:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next | ---|||
+------+ +-----+ +-----+ +-------+------+
| |
V |
+---+ |
| h | |
+---+ |
| +----------------------------------+
V V
+-------+------+ +-------+------+ +-------+------+
| value | next | ---> | value | next | ---> | value | next | ---|||
+-------+------+ +-------+------+ +-------+------+
Наконец, мы устанавливаем ref->next
на значение new
, добавив, таким образом, узел new
, указывающий на конец списка:
+------+ +-----+ +-----+ +-------+------+
| head | | ref | | new | ---> | value | next | ---|||
+------+ +-----+ +-----+ +-------+------+
| | ^
V | |
+---+ | +-------------------------------+
| h | | |
+---+ | |
| +----------------------------------+ |
V V |
+-------+------+ +-------+------+ +-------+------+ |
| value | next | ---> | value | next | ---> | value | next | ---+
+-------+------+ +-------+------+ +-------+------+
Обратите внимание, что ref->next
не указывает на переменную new
,это указывает на то, на что указывает new
.
Поэтому обновление ref
не влияет на head
(или *head
(h
)).В базовом случае, когда список пуст, будет в итоге записывать в *head
(h
), устанавливая его так, чтобы он указывал на новый узел, выделенный из кучи.