Функция insert
здесь работает, потому что current_node.next = _node
является постоянной модификацией объекта в списке, на который указывает head
. После этого вызова, даже если current_node
собирает мусор (это просто временный указатель), у узла, на который он указывал в строке current_node.next = _node
, свойство .next
постоянно изменено.
Вот схема добавления нового узла 3
в список 1->2->nil
:
(before the `until` loop)
+---------+ +---------+
| data: 1 | | data: 2 |
| next: ----> | next: ----> [nil]
+---------+ +---------+
^ ^
| |
head current_node
(after the `until` loop; `current_node.next == nil`)
(and before `current_node.next = _node`)
+---------+ +---------+
| data: 1 | | data: 2 |
| next: ----> | next: ----> [nil]
+---------+ +---------+
^ ^
| |
head current_node
(after `current_node.next = _node`)
+---------+ +---------+ +---------+
| data: 1 | | data: 2 | | data: 3 |
| next: ----> | next: ----> | next: ----> [nil]
+---------+ +---------+ +---------+
^ ^
| |
head current_node
Кстати, этот insert
метод демонстрирует плохую конструкцию; каждая вставка представляет собой O (n) линейную операцию времени, требующую обхода всего списка. Улучшенный дизайн класса LinkedList
предлагает указатель tail
, позволяющий вставлять O (1) с постоянным временем в конец списка. С другой стороны, класс может предложить add_front()
без указателя хвоста, который установит new_head.next = old_head
и head = new_head
.