Обратить однонаправленный связный список Golang
Чтобы обратить (реверсировать) односвязный список в Go, нужно поменять местами ссылки next
между узлами, чтобы они указывали на предыдущий элемент, а не на следующий. При этом голова списка (head
) после обращения будет указывать на последний элемент исходного списка.
Реализация функции для обращения списка
Допустим, у нас уже есть структура LinkedList
и метод Print
, как в предыдущем примере. Мы добавим к этой структуре метод Reverse
, который будет обращать порядок узлов в списке.
Вот как это можно реализовать:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package main import "fmt" // Node представляет элемент односвязного списка type Node struct { value int next *Node } // LinkedList представляет сам список, храня ссылку на первый элемент (голову) type LinkedList struct { head *Node } // Add добавляет новый элемент в конец списка func (list *LinkedList) Add(value int) { newNode := &Node{value: value} if list.head == nil { list.head = newNode return } current := list.head for current.next != nil { current = current.next } current.next = newNode } // Reverse обращает порядок элементов в списке func (list *LinkedList) Reverse() { var prev *Node current := list.head for current != nil { next := current.next // Запоминаем следующий узел current.next = prev // Перенаправляем текущую ссылку на предыдущий узел prev = current // Сдвигаем prev на текущий узел current = next // Переходим к следующему узлу } list.head = prev // Устанавливаем новую голову списка } // Print выводит элементы списка func (list *LinkedList) Print() { current := list.head for current != nil { fmt.Printf("%d -> ", current.value) current = current.next } fmt.Println("nil") } func main() { list := &LinkedList{} // Добавляем элементы list.Add(1) list.Add(2) list.Add(3) list.Add(4) fmt.Println("Исходный список:") list.Print() // 1 -> 2 -> 3 -> 4 -> nil // Обращаем порядок элементов list.Reverse() fmt.Println("Обращённый список:") list.Print() // 4 -> 3 -> 2 -> 1 -> nil } |
Объяснение работы метода Reverse
- Инициализация указателей: создаём указатели
prev
(предыдущий узел) иcurrent
(текущий узел). Изначальноprev
указывает наnil
, аcurrent
— на голову списка. - Перебор узлов: для каждого узла выполняем:
- Сохраняем указатель на следующий узел (
next
). - Меняем ссылку
next
текущего узла на предыдущий узел (prev
), тем самым обращая направление. - Обновляем
prev
иcurrent
, чтобы перейти к следующему узлу.
- Сохраняем указатель на следующий узел (
- Установка новой головы: когда
current
станетnil
, последний обработанный узел (prev
) станет новой головой списка.
Пример работы
- Исходный список:
1 -> 2 -> 3 -> 4 -> nil
. - Обращённый список после вызова
Reverse
:4 -> 3 -> 2 -> 1 -> nil
.
Этот метод работает за линейное время O(n)O(n), так как мы проходим по каждому узлу один раз.
Recommended Posts
Golang Sarama: настройка Partitioner
20.03.2024