|
72 | 72 | ## * `deques module <deques.html>`_ for double-ended queues
|
73 | 73 | ## * `sharedlist module <sharedlist.html>`_ for shared singly-linked lists
|
74 | 74 |
|
| 75 | +import std/private/since |
75 | 76 |
|
76 | 77 | when not defined(nimhygiene):
|
77 | 78 | {.pragma: dirty.}
|
@@ -178,6 +179,26 @@ proc newSinglyLinkedNode*[T](value: T): <//>(SinglyLinkedNode[T]) =
|
178 | 179 | new(result)
|
179 | 180 | result.value = value
|
180 | 181 |
|
| 182 | +func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} = |
| 183 | + ## Creates a new `SinglyLinkedList` from members of `elems`. |
| 184 | + runnableExamples: |
| 185 | + import sequtils |
| 186 | + let a = [1, 2, 3, 4, 5].toSinglyLinkedList |
| 187 | + assert a.toSeq == [1, 2, 3, 4, 5] |
| 188 | + result = initSinglyLinkedList[T]() |
| 189 | + for elem in elems.items: |
| 190 | + result.append(elem) |
| 191 | + |
| 192 | +func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} = |
| 193 | + ## Creates a new `DoublyLinkedList` from members of `elems`. |
| 194 | + runnableExamples: |
| 195 | + import sequtils |
| 196 | + let a = [1, 2, 3, 4, 5].toDoublyLinkedList |
| 197 | + assert a.toSeq == [1, 2, 3, 4, 5] |
| 198 | + result = initDoublyLinkedList[T]() |
| 199 | + for elem in elems.items: |
| 200 | + result.append(elem) |
| 201 | + |
181 | 202 | template itemsListImpl() {.dirty.} =
|
182 | 203 | var it = L.head
|
183 | 204 | while it != nil:
|
@@ -435,7 +456,60 @@ proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} =
|
435 | 456 | assert a.contains(9)
|
436 | 457 | prepend(L, newSinglyLinkedNode(value))
|
437 | 458 |
|
438 |
| - |
| 459 | +func copy*[T](a: SinglyLinkedList[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} = |
| 460 | + ## Creates a shallow copy of `a`. |
| 461 | + runnableExamples: |
| 462 | + import sequtils |
| 463 | + type Foo = ref object |
| 464 | + x: int |
| 465 | + var |
| 466 | + f = Foo(x: 1) |
| 467 | + a = [f].toSinglyLinkedList |
| 468 | + let b = a.copy |
| 469 | + a.add [f].toSinglyLinkedList |
| 470 | + assert a.toSeq == [f, f] |
| 471 | + assert b.toSeq == [f] # b isn't modified... |
| 472 | + f.x = 42 |
| 473 | + assert a.head.value.x == 42 |
| 474 | + assert b.head.value.x == 42 # ... but the elements are not deep copied |
| 475 | + |
| 476 | + let c = [1, 2, 3].toSinglyLinkedList |
| 477 | + assert $c == $c.copy |
| 478 | + result = initSinglyLinkedList[T]() |
| 479 | + for x in a.items: |
| 480 | + result.append(x) |
| 481 | + |
| 482 | +proc addMoved*[T](a, b: var SinglyLinkedList[T]) {.since: (1, 5, 1).} = |
| 483 | + ## Moves `b` to the end of `a`. Efficiency: O(1). |
| 484 | + ## Note that `b` becomes empty after the operation unless it has the same address as `a`. |
| 485 | + ## Self-adding results in a cycle. |
| 486 | + ## |
| 487 | + ## See also: |
| 488 | + ## * `add proc <#add,T,T>`_ |
| 489 | + ## for adding a copy of a list |
| 490 | + runnableExamples: |
| 491 | + import sequtils, std/enumerate, std/sugar |
| 492 | + var |
| 493 | + a = [1, 2, 3].toSinglyLinkedList |
| 494 | + b = [4, 5].toSinglyLinkedList |
| 495 | + c = [0, 1].toSinglyLinkedList |
| 496 | + a.addMoved b |
| 497 | + assert a.toSeq == [1, 2, 3, 4, 5] |
| 498 | + assert b.toSeq == [] |
| 499 | + c.addMoved c |
| 500 | + let s = collect: |
| 501 | + for i, ci in enumerate(c): |
| 502 | + if i == 6: break |
| 503 | + ci |
| 504 | + assert s == [0, 1, 0, 1, 0, 1] |
| 505 | + if a.tail != nil: |
| 506 | + a.tail.next = b.head |
| 507 | + a.tail = b.tail |
| 508 | + if a.head == nil: |
| 509 | + a.head = b.head |
| 510 | + if a.addr != b.addr: |
| 511 | + b.head = nil |
| 512 | + b.tail = nil |
439 | 513 |
|
440 | 514 | proc append*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) =
|
441 | 515 | ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1).
|
@@ -523,6 +597,78 @@ proc prepend*[T](L: var DoublyLinkedList[T], value: T) =
|
523 | 597 | assert a.contains(9)
|
524 | 598 | prepend(L, newDoublyLinkedNode(value))
|
525 | 599 |
|
| 600 | +func copy*[T](a: DoublyLinkedList[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} = |
| 601 | + ## Creates a shallow copy of `a`. |
| 602 | + runnableExamples: |
| 603 | + type Foo = ref object |
| 604 | + x: int |
| 605 | + var f = Foo(x: 1) |
| 606 | + let |
| 607 | + a = [f].toDoublyLinkedList |
| 608 | + b = a.copy |
| 609 | + f.x = 42 |
| 610 | + assert a.head.value.x == 42 |
| 611 | + assert b.head.value.x == 42 |
| 612 | + |
| 613 | + let c = [1, 2, 3].toDoublyLinkedList |
| 614 | + assert $c == $c.copy |
| 615 | + result = initDoublyLinkedList[T]() |
| 616 | + for x in a.items: |
| 617 | + result.append(x) |
| 618 | + |
| 619 | +proc addMoved*[T](a, b: var DoublyLinkedList[T]) {.since: (1, 5, 1).} = |
| 620 | + ## Moves `b` to the end of `a`. Efficiency: O(1). |
| 621 | + ## Note that `b` becomes empty after the operation unless it has the same address as `a`. |
| 622 | + ## Self-adding results in a cycle. |
| 623 | + ## |
| 624 | + ## See also: |
| 625 | + ## * `add proc <#add,T,T>`_ |
| 626 | + ## for adding a copy of a list |
| 627 | + runnableExamples: |
| 628 | + import sequtils, std/enumerate, std/sugar |
| 629 | + var |
| 630 | + a = [1, 2, 3].toDoublyLinkedList |
| 631 | + b = [4, 5].toDoublyLinkedList |
| 632 | + c = [0, 1].toDoublyLinkedList |
| 633 | + a.addMoved b |
| 634 | + assert a.toSeq == [1, 2, 3, 4, 5] |
| 635 | + assert b.toSeq == [] |
| 636 | + c.addMoved c |
| 637 | + let s = collect: |
| 638 | + for i, ci in enumerate(c): |
| 639 | + if i == 6: break |
| 640 | + ci |
| 641 | + assert s == [0, 1, 0, 1, 0, 1] |
| 642 | + if b.head != nil: |
| 643 | + b.head.prev = a.tail |
| 644 | + if a.tail != nil: |
| 645 | + a.tail.next = b.head |
| 646 | + a.tail = b.tail |
| 647 | + if a.head == nil: |
| 648 | + a.head = b.head |
| 649 | + if a.addr != b.addr: |
| 650 | + b.head = nil |
| 651 | + b.tail = nil |
| 652 | + |
| 653 | +proc add*[T: SomeLinkedList](a: var T, b: T) {.since: (1, 5, 1).} = |
| 654 | + ## Appends a shallow copy of `b` to the end of `a`. |
| 655 | + ## |
| 656 | + ## See also: |
| 657 | + ## * `addMoved proc <#addMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_ |
| 658 | + ## * `addMoved proc <#addMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_ |
| 659 | + ## for moving the second list instead of copying |
| 660 | + runnableExamples: |
| 661 | + import sequtils |
| 662 | + var a = [1, 2, 3].toSinglyLinkedList |
| 663 | + let b = [4, 5].toSinglyLinkedList |
| 664 | + a.add b |
| 665 | + assert a.toSeq == [1, 2, 3, 4, 5] |
| 666 | + assert b.toSeq == [4, 5] |
| 667 | + a.add a |
| 668 | + assert a.toSeq == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] |
| 669 | + var tmp = b.copy |
| 670 | + a.addMoved tmp |
| 671 | + |
526 | 672 | proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) =
|
527 | 673 | ## Removes a node `n` from `L`. Efficiency: O(1).
|
528 | 674 | runnableExamples:
|
|
0 commit comments