github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/list/doubly_linkedlist.go (about) 1 package list 2 3 import ( 4 "sync/atomic" 5 ) 6 7 var ( 8 _ LinkedList[struct{}] = (*doublyLinkedList[struct{}])(nil) // Type check assertion 9 ) 10 11 type nodeElementInListStatus uint8 12 13 const ( 14 notInList nodeElementInListStatus = iota 15 emtpyList 16 theOnlyOne 17 theFirstButNotTheLast 18 theLastButNotTheFirst 19 inMiddle 20 ) 21 22 type doublyLinkedList[T comparable] struct { 23 root nodeElement[T] 24 len atomic.Int64 25 } 26 27 func NewLinkedList[T comparable]() LinkedList[T] { 28 return new(doublyLinkedList[T]).init() 29 } 30 31 func (l *doublyLinkedList[T]) getRoot() NodeElement[T] { 32 return &l.root 33 } 34 35 func (l *doublyLinkedList[T]) getRootHead() NodeElement[T] { 36 return l.root.next 37 } 38 39 func (l *doublyLinkedList[T]) setRootHead(targetE NodeElement[T]) { 40 l.root.next = targetE 41 } 42 43 func (l *doublyLinkedList[T]) getRootTail() NodeElement[T] { 44 return l.root.prev 45 } 46 47 func (l *doublyLinkedList[T]) setRootTail(targetE NodeElement[T]) { 48 l.root.prev = targetE 49 } 50 51 func (l *doublyLinkedList[T]) init() *doublyLinkedList[T] { 52 l.root.list = l 53 l.setRootHead(&l.root) 54 l.setRootTail(&l.root) 55 l.len.Store(0) 56 return l 57 } 58 59 func (l *doublyLinkedList[T]) Len() int64 { 60 return l.len.Load() 61 } 62 63 func (l *doublyLinkedList[T]) checkElement(targetE NodeElement[T]) (*nodeElement[T], nodeElementInListStatus) { 64 if targetE == nil { 65 return nil, notInList 66 } 67 at, ok := targetE.(*nodeElement[T]) 68 if !ok || at.list != l || at.hasLock() != l.root.hasLock() { 69 return nil, notInList 70 } 71 if l.len.Load() == 0 { 72 return l.getRoot().(*nodeElement[T]), emtpyList 73 } 74 75 // mem address compare 76 switch { 77 case at.GetPrev() == nil && at.GetNext() == nil: 78 // targetE is the first one and the last one 79 if l.getRootHead() != targetE || l.getRootTail() != targetE { 80 return nil, notInList 81 } 82 return at, theOnlyOne 83 case at.GetPrev() == nil && at.GetNext() != nil: 84 // targetE is the first one but not the last one 85 if at.GetNext().GetPrev() != targetE { 86 return nil, notInList 87 } 88 // Ignore l.setRootTail (tail) 89 return at, theFirstButNotTheLast 90 case at.GetPrev() != nil && at.GetNext() == nil: 91 // targetE is the last one but not the first one 92 if at.GetPrev().GetNext() != targetE { 93 return nil, notInList 94 } 95 // Ignore l.setRootHead (head) 96 return at, theLastButNotTheFirst 97 case at.GetPrev() != nil && at.GetNext() != nil: 98 // targetE is neither the first one nor the last one 99 if at.GetPrev().GetNext() != targetE && at.GetNext().GetPrev() != targetE { 100 return nil, notInList 101 } 102 return at, inMiddle 103 } 104 return nil, notInList 105 } 106 107 func (l *doublyLinkedList[T]) append(e *nodeElement[T]) NodeElement[T] { 108 e.list = l 109 e.next, e.prev = nil, nil 110 111 if l.len.Load() == 0 { 112 // empty list, new append element is the first one 113 l.setRootHead(e) 114 l.setRootTail(e) 115 l.len.Add(1) 116 return e 117 } 118 119 lastOne := l.getRootTail().(*nodeElement[T]) 120 lastOne.next = e 121 e.prev, e.next = lastOne, nil 122 l.setRootTail(e) 123 124 l.len.Add(1) 125 return e 126 } 127 128 func (l *doublyLinkedList[T]) Append(elements ...NodeElement[T]) []NodeElement[T] { 129 if l.getRootTail() == nil { 130 return nil 131 } 132 for i := 0; i < len(elements); i++ { 133 if elements[i] == nil { 134 continue 135 } 136 e, ok := elements[i].(*nodeElement[T]) 137 if !ok || e.list != l || l.root.hasLock() != e.hasLock() { 138 continue 139 } 140 elements[i] = l.append(e) 141 } 142 return elements 143 } 144 145 func (l *doublyLinkedList[T]) AppendValue(values ...T) []NodeElement[T] { 146 // FIXME How to decrease the memory allocation for each operation? 147 // sync.Pool reused the released objects? 148 if len(values) <= 0 { 149 return nil 150 } else if len(values) == 1 { 151 return l.Append(newNodeElement(values[0], l)) 152 } 153 154 newElements := make([]NodeElement[T], 0, len(values)) 155 for _, v := range values { 156 newElements = append(newElements, newNodeElement(v, l)) 157 } 158 return l.Append(newElements...) 159 } 160 161 func (l *doublyLinkedList[T]) insertAfter(newE, at *nodeElement[T]) *nodeElement[T] { 162 if at == l.getRoot() { 163 newE.prev = nil 164 } else { 165 newE.prev = at 166 } 167 168 if l.len.Load() == 0 { 169 newE.next = nil 170 l.setRootHead(newE) 171 l.setRootTail(newE) 172 } else { 173 newE.next = at.GetNext() 174 at.next = newE 175 if newE.GetNext() != nil { 176 newE.GetNext().(*nodeElement[T]).prev = newE 177 } 178 } 179 l.len.Add(1) 180 return newE 181 } 182 183 func (l *doublyLinkedList[T]) InsertAfter(v T, dstE NodeElement[T]) NodeElement[T] { 184 at, status := l.checkElement(dstE) 185 if status == notInList { 186 return nil 187 } 188 189 newE := newNodeElement(v, l) 190 newE = l.insertAfter(newE, at) 191 switch status { 192 case theOnlyOne, theLastButNotTheFirst: 193 l.setRootTail(newE) 194 default: 195 196 } 197 return newE 198 } 199 200 func (l *doublyLinkedList[T]) insertBefore(newE, at *nodeElement[T]) *nodeElement[T] { 201 if at == l.getRoot() { 202 newE.next = nil 203 } else { 204 newE.next = at 205 } 206 if l.len.Load() == 0 { 207 newE.prev = nil 208 l.setRootHead(newE) 209 l.setRootTail(newE) 210 } else { 211 newE.prev = at.prev 212 at.prev = newE 213 if newE.GetPrev() != nil { 214 newE.GetPrev().(*nodeElement[T]).next = newE 215 } 216 } 217 l.len.Add(1) 218 return newE 219 } 220 221 func (l *doublyLinkedList[T]) InsertBefore(v T, dstE NodeElement[T]) NodeElement[T] { 222 at, status := l.checkElement(dstE) 223 if status == notInList { 224 return nil 225 } 226 newE := newNodeElement(v, l) 227 newE = l.insertBefore(newE, at) 228 switch status { 229 case theOnlyOne, theFirstButNotTheLast: 230 l.setRootHead(newE) 231 default: 232 233 } 234 return newE 235 } 236 237 func (l *doublyLinkedList[T]) Remove(targetE NodeElement[T]) NodeElement[T] { 238 var ( 239 at *nodeElement[T] 240 status nodeElementInListStatus 241 ) 242 243 // doubly linked list removes element is free to do iteration, but we have to check the value if equals. 244 // avoid memory leaks 245 switch at, status = l.checkElement(targetE); status { 246 case theOnlyOne: 247 l.setRootHead(l.getRoot()) 248 l.setRootTail(l.getRoot()) 249 case theFirstButNotTheLast: 250 l.setRootHead(at.GetNext()) 251 at.GetNext().(*nodeElement[T]).prev = nil 252 case theLastButNotTheFirst: 253 l.setRootTail(at.GetPrev()) 254 at.GetPrev().(*nodeElement[T]).next = nil 255 case inMiddle: 256 at.GetPrev().(*nodeElement[T]).next = at.next 257 at.GetNext().(*nodeElement[T]).prev = at.prev 258 default: 259 return nil 260 } 261 262 // avoid memory leaks 263 at.list = nil 264 at.next = nil 265 at.prev = nil 266 if at.lock != nil { 267 at.lock = nil 268 } 269 l.len.Add(-1) 270 return at 271 } 272 273 func (l *doublyLinkedList[T]) ForEach(fn func(idx int64, e NodeElement[T])) { 274 if fn == nil || l.len.Load() == 0 || 275 l.getRoot() == l.getRootHead() && l.getRoot() == l.getRootTail() { 276 return 277 } 278 279 var ( 280 iterator = l.getRoot().GetNext() 281 idx int64 = 0 282 ) 283 for iterator != nil { 284 // Avoid remove in iteration result in memory leak 285 next := iterator.GetNext() 286 fn(idx, iterator) 287 iterator, idx = next, idx+1 288 } 289 } 290 291 func (l *doublyLinkedList[T]) ReverseForEach(fn func(idx int64, e NodeElement[T])) { 292 if fn == nil || l.len.Load() == 0 || 293 l.getRoot() == l.getRootHead() && l.getRoot() == l.getRootTail() { 294 return 295 } 296 297 var ( 298 iterator = l.getRoot().GetPrev() 299 idx int64 = 0 300 ) 301 for iterator != nil { 302 // Avoid remove in iteration result in memory leak 303 prev := iterator.GetPrev() 304 fn(idx, iterator) 305 iterator, idx = prev, idx+1 306 } 307 } 308 309 func (l *doublyLinkedList[T]) FindFirst(targetV T, compareFn ...func(e NodeElement[T]) bool) (NodeElement[T], bool) { 310 if l.len.Load() == 0 { 311 return nil, false 312 } 313 314 if len(compareFn) <= 0 { 315 compareFn = []func(e NodeElement[T]) bool{ 316 func(e NodeElement[T]) bool { 317 return e.GetValue() == targetV 318 }, 319 } 320 } 321 322 var iterator = l.getRoot() 323 for iterator.HasNext() { 324 if compareFn[0](iterator.GetNext()) { 325 return iterator.GetNext(), true 326 } 327 iterator = iterator.GetNext() 328 } 329 return nil, false 330 } 331 332 func (l *doublyLinkedList[T]) Front() NodeElement[T] { 333 return l.root.GetNext() 334 } 335 336 func (l *doublyLinkedList[T]) Back() NodeElement[T] { 337 return l.root.GetPrev() 338 } 339 340 func (l *doublyLinkedList[T]) PushFront(v T) NodeElement[T] { 341 return l.InsertBefore(v, l.getRootHead()) 342 } 343 344 func (l *doublyLinkedList[T]) PushBack(v T) NodeElement[T] { 345 return l.InsertAfter(v, l.getRootTail()) 346 } 347 348 func (l *doublyLinkedList[T]) move(src, dst *nodeElement[T]) bool { 349 if src == dst { 350 return false 351 } 352 // Ordinarily, it is move src next to dst 353 if src.HasPrev() { // src is not the first node 354 src.GetPrev().(*nodeElement[T]).next = src.next 355 } 356 if src.HasNext() { // src is not the last node 357 src.GetNext().(*nodeElement[T]).prev = src.prev 358 } 359 360 if dst == l.getRoot() { // dst is the first node 361 src.prev = nil 362 } else { 363 src.prev = dst 364 } 365 src.next = dst.GetNext() 366 if src.HasNext() { // src updated but not the last node 367 src.GetNext().(*nodeElement[T]).prev = src 368 } 369 370 dst.next = src 371 return true 372 } 373 374 func (l *doublyLinkedList[T]) MoveToFront(targetE NodeElement[T]) { 375 moved := false 376 src, status := l.checkElement(targetE) 377 switch status { 378 case theLastButNotTheFirst: 379 defer func(prev NodeElement[T]) { 380 if moved { 381 l.setRootHead(src) 382 l.setRootTail(prev) 383 } 384 }(src.GetPrev()) // register the element immediately 385 case notInList, theOnlyOne, theFirstButNotTheLast: 386 return 387 default: 388 389 } 390 moved = l.move(src, &l.root) 391 } 392 393 func (l *doublyLinkedList[T]) MoveToBack(targetE NodeElement[T]) { 394 moved := false 395 src, status := l.checkElement(targetE) 396 switch status { 397 case theFirstButNotTheLast: 398 defer func(next NodeElement[T]) { 399 if moved { 400 l.setRootHead(next) 401 l.setRootTail(src) 402 } 403 }(src.GetNext()) // register the element immediately 404 case notInList, theLastButNotTheFirst, theOnlyOne: 405 return 406 default: 407 408 } 409 moved = l.move(src, l.getRootTail().(*nodeElement[T])) 410 } 411 412 func (l *doublyLinkedList[T]) MoveBefore(srcE, dstE NodeElement[T]) { 413 var ( 414 moved = false 415 dst, src *nodeElement[T] 416 dstStatus, srcStatus nodeElementInListStatus 417 ) 418 switch dst, dstStatus = l.checkElement(dstE); dstStatus { 419 case notInList, theOnlyOne: 420 return 421 default: 422 423 } 424 switch src, srcStatus = l.checkElement(srcE); srcStatus { 425 case notInList, theOnlyOne: 426 return 427 case theFirstButNotTheLast: 428 defer func(next NodeElement[T]) { 429 // src from the head to the middle 430 if moved && dstStatus == theLastButNotTheFirst || dstStatus == inMiddle { 431 l.setRootHead(next) 432 } 433 }(src.GetNext()) // register the element immediately 434 case theLastButNotTheFirst: 435 defer func(prev NodeElement[T]) { 436 // src from the tail to the head 437 if moved && dstStatus == theFirstButNotTheLast { 438 l.setRootHead(src) 439 l.setRootTail(prev) 440 } 441 if moved && dstStatus == inMiddle { 442 l.setRootTail(prev) 443 } 444 }(src.GetPrev()) // register the element immediately 445 case inMiddle: 446 defer func() { 447 // src as the new first node 448 if moved && dstStatus == theFirstButNotTheLast { 449 l.setRootHead(src) 450 } 451 }() 452 default: 453 454 } 455 if dst.GetPrev() == nil { 456 return 457 } 458 dstPrev := dst.GetPrev().(*nodeElement[T]) 459 moved = l.move(src, dstPrev) 460 } 461 462 func (l *doublyLinkedList[T]) MoveAfter(srcE, dstE NodeElement[T]) { 463 var ( 464 moved = false 465 dst, src *nodeElement[T] 466 dstStatus, srcStatus nodeElementInListStatus 467 ) 468 switch dst, dstStatus = l.checkElement(dstE); dstStatus { 469 case notInList, theOnlyOne: 470 return 471 default: 472 473 } 474 switch src, srcStatus = l.checkElement(srcE); srcStatus { 475 case notInList, theOnlyOne: 476 return 477 case theFirstButNotTheLast: 478 defer func(next NodeElement[T]) { 479 // src from the head to the tail 480 if moved && dstStatus == theLastButNotTheFirst { 481 l.setRootHead(next) 482 l.setRootTail(src) 483 } 484 // src from the head to the middle 485 if moved && dstStatus == inMiddle { 486 l.setRootHead(next) 487 } 488 }(src.GetNext()) // register the element immediately 489 case theLastButNotTheFirst: 490 defer func(prev NodeElement[T]) { 491 // src from the tail to the middle 492 if moved && dstStatus == theFirstButNotTheLast || dstStatus == inMiddle { 493 l.setRootTail(prev) 494 } 495 }(src.GetPrev()) 496 case inMiddle: 497 defer func() { 498 if moved && dstStatus == theLastButNotTheFirst { 499 l.setRootTail(src) 500 } 501 }() 502 default: 503 504 } 505 506 moved = l.move(src, dst) 507 } 508 509 func (l *doublyLinkedList[T]) PushFrontList(src LinkedList[T]) { 510 if dl, ok := src.(*doublyLinkedList[T]); !ok || dl != nil && dl.getRoot() == l.getRoot() { 511 // avoid type mismatch and self copy 512 return 513 } 514 515 for i, e := src.Len(), src.Back(); i > 0; i-- { 516 prev := e.GetPrev() 517 // Clean the node element reference, not a required operation 518 e.(*nodeElement[T]).list = l 519 e.(*nodeElement[T]).prev = nil 520 e.(*nodeElement[T]).next = nil 521 l.insertAfter(e.(*nodeElement[T]), &l.root) 522 e = prev 523 } 524 } 525 526 func (l *doublyLinkedList[T]) PushBackList(src LinkedList[T]) { 527 if dl, ok := src.(*doublyLinkedList[T]); !ok || dl != nil && dl.getRoot() == l.getRoot() { 528 // avoid type mismatch and self copy 529 return 530 } 531 for i, e := src.Len(), src.Front(); i > 0; i-- { 532 next := e.GetNext() 533 // Clean the node element reference, not a required operation 534 e.(*nodeElement[T]).list = l 535 e.(*nodeElement[T]).prev = nil 536 e.(*nodeElement[T]).next = nil 537 l.Append(e) 538 e = next 539 } 540 }