github.com/go-playground/pkg/v5@v5.29.1/container/list/doubly_linked.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package listext 5 6 // Node is an element of the doubly linked list. 7 type Node[V any] struct { 8 next, prev *Node[V] 9 Value V 10 } 11 12 // Next returns the nodes next Value or nil if it is at the tail. 13 func (n *Node[V]) Next() *Node[V] { 14 return n.next 15 } 16 17 // Prev returns the nodes previous Value or nil if it is at the head. 18 func (n *Node[V]) Prev() *Node[V] { 19 return n.prev 20 } 21 22 // DoublyLinkedList is a doubly linked list 23 type DoublyLinkedList[V any] struct { 24 head, tail *Node[V] 25 len int 26 } 27 28 // NewDoublyLinked creates a DoublyLinkedList for use. 29 func NewDoublyLinked[V any]() *DoublyLinkedList[V] { 30 return new(DoublyLinkedList[V]) 31 } 32 33 // PushFront adds an element first in the list. 34 func (d *DoublyLinkedList[V]) PushFront(v V) *Node[V] { 35 node := &Node[V]{ 36 Value: v, 37 } 38 d.pushFront(node) 39 return d.head 40 } 41 42 func (d *DoublyLinkedList[V]) pushFront(node *Node[V]) { 43 node.next = d.head 44 node.prev = nil 45 46 if d.head == nil { 47 d.tail = node 48 } else { 49 d.head.prev = node 50 } 51 d.head = node 52 d.len++ 53 } 54 55 // PopFront removes the first element and returns it or nil. 56 func (d *DoublyLinkedList[V]) PopFront() *Node[V] { 57 if d.IsEmpty() { 58 return nil 59 } 60 61 node := d.head 62 d.head = node.next 63 if d.head == nil { 64 d.tail = nil 65 } else { 66 d.head.prev = nil 67 } 68 d.len-- 69 // ensure no leakage 70 node.next, node.prev = nil, nil 71 return node 72 } 73 74 // PushBack appends an element to the back of a list. 75 func (d *DoublyLinkedList[V]) PushBack(v V) *Node[V] { 76 node := &Node[V]{ 77 Value: v, 78 } 79 d.pushBack(node) 80 return d.tail 81 } 82 83 func (d *DoublyLinkedList[V]) pushBack(node *Node[V]) { 84 node.prev = d.tail 85 node.next = nil 86 87 if d.tail == nil { 88 d.head = node 89 } else { 90 d.tail.next = node 91 } 92 d.tail = node 93 d.len++ 94 } 95 96 // PushAfter pushes the supplied Value after the supplied node. 97 // 98 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 99 func (d *DoublyLinkedList[V]) PushAfter(node *Node[V], v V) *Node[V] { 100 newNode := &Node[V]{ 101 Value: v, 102 } 103 d.moveAfter(node, newNode) 104 return newNode 105 } 106 107 // MoveAfter moves the `moving` node after the supplied `node`. 108 // 109 // The supplied `node` and `moving` nodes must be attached to the current list otherwise 110 // undefined behaviour could occur. 111 func (d *DoublyLinkedList[V]) MoveAfter(node *Node[V], moving *Node[V]) { 112 // first detach node were moving after, in case it was already attached somewhere else in the list. 113 d.Remove(moving) 114 d.moveAfter(node, moving) 115 } 116 117 func (d *DoublyLinkedList[V]) moveAfter(node *Node[V], moving *Node[V]) { 118 next := node.next 119 120 // no next means node == d.tail 121 if next == nil { 122 d.pushBack(moving) 123 } else { 124 node.next = moving 125 moving.prev = node 126 moving.next = next 127 next.prev = moving 128 d.len++ 129 } 130 } 131 132 // PushBefore pushes the supplied Value before the supplied node. 133 // 134 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 135 func (d *DoublyLinkedList[V]) PushBefore(node *Node[V], v V) *Node[V] { 136 newNode := &Node[V]{ 137 Value: v, 138 } 139 d.moveBefore(node, newNode) 140 return newNode 141 } 142 143 // InsertBefore inserts the supplied node before the supplied node. 144 // 145 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 146 func (d *DoublyLinkedList[V]) InsertBefore(node *Node[V], inserting *Node[V]) { 147 d.moveBefore(node, inserting) 148 } 149 150 // InsertAfter inserts the supplied node after the supplied node. 151 // 152 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 153 func (d *DoublyLinkedList[V]) InsertAfter(node *Node[V], inserting *Node[V]) { 154 d.moveAfter(node, inserting) 155 } 156 157 // MoveBefore moves the `moving` node before the supplied `node`. 158 // 159 // The supplied `node` and `moving` nodes must be attached to the current list otherwise 160 // undefined behaviour could occur. 161 func (d *DoublyLinkedList[V]) MoveBefore(node *Node[V], moving *Node[V]) { 162 // first detach node were moving after, in case it was already attached somewhere else in the list. 163 d.Remove(moving) 164 d.moveBefore(node, moving) 165 } 166 167 func (d *DoublyLinkedList[V]) moveBefore(node *Node[V], moving *Node[V]) { 168 prev := node.prev 169 170 // no prev means node == d.head 171 if prev == nil { 172 d.pushFront(moving) 173 } else { 174 node.prev = moving 175 moving.next = node 176 moving.prev = prev 177 prev.next = moving 178 d.len++ 179 } 180 } 181 182 // PopBack removes the last element from a list and returns it or nil. 183 func (d *DoublyLinkedList[V]) PopBack() *Node[V] { 184 if d.IsEmpty() { 185 return nil 186 } 187 188 node := d.tail 189 d.tail = node.prev 190 191 if d.tail == nil { 192 d.head = nil 193 } else { 194 d.tail.next = nil 195 } 196 d.len-- 197 // ensure no leakage 198 node.next, node.prev = nil, nil 199 return node 200 } 201 202 // Front returns the front/head element for use without removing it or nil list is empty. 203 func (d *DoublyLinkedList[V]) Front() *Node[V] { 204 return d.head 205 } 206 207 // Back returns the end/tail element for use without removing it or nil list is empty. 208 func (d *DoublyLinkedList[V]) Back() *Node[V] { 209 return d.tail 210 } 211 212 // Remove removes the provided element from the Linked List. 213 // 214 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 215 func (d *DoublyLinkedList[V]) Remove(node *Node[V]) { 216 if node.prev == nil { 217 // is head node 218 _ = d.PopFront() 219 } else if node.next == nil { 220 // is tail node 221 _ = d.PopBack() 222 } else { 223 // is both head and tail nodes, must remap 224 node.next.prev = node.prev 225 node.prev.next = node.next 226 // ensure no leakage 227 node.next, node.prev = nil, nil 228 d.len-- 229 } 230 } 231 232 // MoveToFront moves the provided node to the front/head. 233 // 234 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 235 func (d *DoublyLinkedList[V]) MoveToFront(node *Node[V]) { 236 d.Remove(node) 237 d.pushFront(node) 238 } 239 240 // InsertAtFront pushes the provided node to the front/head. 241 // 242 // The supplied node must not be attached to any list otherwise undefined behaviour could occur. 243 func (d *DoublyLinkedList[V]) InsertAtFront(node *Node[V]) { 244 d.pushFront(node) 245 } 246 247 // MoveToBack moves the provided node to the end/tail. 248 // 249 // The supplied node must be attached to the current list otherwise undefined behaviour could occur. 250 func (d *DoublyLinkedList[V]) MoveToBack(node *Node[V]) { 251 d.Remove(node) 252 d.pushBack(node) 253 } 254 255 // InsertAtBack pushes the provided node to the back/tail. 256 // 257 // The supplied node must not be attached to any list otherwise undefined behaviour could occur. 258 func (d *DoublyLinkedList[V]) InsertAtBack(node *Node[V]) { 259 d.pushBack(node) 260 } 261 262 // IsEmpty returns true if the list is empty. 263 func (d *DoublyLinkedList[V]) IsEmpty() bool { 264 return d.len == 0 265 } 266 267 // Len returns length of the Linked List. 268 func (d *DoublyLinkedList[V]) Len() int { 269 return d.len 270 } 271 272 // Clear removes all elements from the Linked List. 273 func (d *DoublyLinkedList[V]) Clear() { 274 // must loop and clean up references to each other. 275 for { 276 if d.PopBack() == nil { 277 break 278 } 279 } 280 d.head, d.tail, d.len = nil, nil, 0 281 }