Рассмотрим список:
1 -> 2 -> 3 -> 4 -> NULL
^ ^
| |
first rest
Где first
указывает на первый узел, а остальные указывают на узел рядом с first
.
Поскольку список не пуст и список не содержит одного узла, мы делаем рекурсивный вызов reverse
, чтобы перевернуть список, на который указывает rest
. Вот как выглядит список после обращения к остальной части списка:
1 -> 2 <- 3 <- 4
^ | ^
| NULL |
first rest
Как видно, rest
теперь указывает на перевернутый список, в котором 4
в начале и 2
в конце списка. Следующий указатель узла 2
- NULL
.
Теперь нам нужно добавить первый узел в конец списка перевернутых остатков. Чтобы добавить что-либо в конец списка, нам нужен доступ к последнему узлу списка. В этом случае нам нужен доступ к последнему узлу списка перевернутых остатков. Посмотрите на диаграмму, first -> next
указывает на последний перевернутый список остальных узлов. Следовательно, first -> next -> next
будет следующим указателем последнего узла в списке обращенных остатков. Теперь нам нужно указать first
, поэтому мы делаем:
first -> next -> next = first;
После этого шага список выглядит так:
1 <- 2 <- 3 <- 4
^ -> ^
| |
first rest
Теперь поле next
последнего узла списка должно быть NULL
. Но сейчас дело не в этом. Поле next
последнего узла (узел 1
) указывает на узел перед ним (узел 2
). Чтобы это исправить мы делаем:
first -> next = NULL;
После этого список выглядит так:
NULL <- 1 <- 2 <- 3 <- 4
^ ^
| |
first rest
Как видно, список теперь правильно перевернут, с rest
, указывающим на заголовок перевернутого списка.
Нам нужно вернуть новый указатель головы, чтобы изменения отражались в вызывающей функции. Но это функция void
, а head
передается как двойной указатель, поэтому при изменении значения *head
вызывающая функция увидит измененную голову:
*head = rest;