On this page
std/lists
Source EditImplementation of:
- singly linked lists
- doubly linked lists
- singly linked rings (circular lists)
- doubly linked rings (circular lists)
Basic Usage
Because it makes no sense to do otherwise, the next
and prev
pointers are not hidden from you and can be manipulated directly for efficiency.
Lists
Example:
import std/lists
var list = initDoublyLinkedList[int]()
let
a = newDoublyLinkedNode[int](3)
b = newDoublyLinkedNode[int](7)
c = newDoublyLinkedNode[int](9)
list.add(a)
list.add(b)
list.prepend(c)
assert a.next == b
assert a.prev == c
assert c.next == a
assert c.next.next == b
assert c.prev == nil
assert b.next == nil
Rings
Example:
import std/lists
var ring = initSinglyLinkedRing[int]()
let
a = newSinglyLinkedNode[int](3)
b = newSinglyLinkedNode[int](7)
c = newSinglyLinkedNode[int](9)
ring.add(a)
ring.add(b)
ring.prepend(c)
assert c.next == a
assert a.next == b
assert c.next.next == b
assert b.next == c
assert c.next.next.next == c
See also
- deques module for double-ended queues
Imports
Types
-
DoublyLinkedList[T] = object head*: DoublyLinkedNode[T] tail* {.cursor.}: DoublyLinkedNode[T]
- A doubly linked list. Source Edit
-
DoublyLinkedNodeObj[T] = object next*: DoublyLinkedNode[T] prev* {.cursor.}: DoublyLinkedNode[T] value*: T
-
A node of a doubly linked list.
It consists of a
Source Editvalue
field, and pointers tonext
andprev
. -
SinglyLinkedList[T] = object head*: SinglyLinkedNode[T] tail* {.cursor.}: SinglyLinkedNode[T]
- A singly linked list. Source Edit
-
SinglyLinkedNodeObj[T] = object next*: SinglyLinkedNode[T] value*: T
-
A node of a singly linked list.
It consists of a
Source Editvalue
field, and a pointer tonext
.
Procs
-
proc add[T: SomeLinkedList](a: var T; b: T)
-
Appends a shallow copy of
b
to the end ofa
.See also:
- addMoved proc
- addMoved proc for moving the second list instead of copying
Example:
Source Editfrom std/sequtils import toSeq var a = [1, 2, 3].toSinglyLinkedList let b = [4, 5].toSinglyLinkedList a.add(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [4, 5] a.add(a) assert a.toSeq == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
-
proc add[T](L: var DoublyLinkedList[T]; n: DoublyLinkedNode[T])
-
Appends (adds to the end) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a value
- prepend proc for prepending a node
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedList[int]() let n = newDoublyLinkedNode[int](9) a.add(n) assert a.contains(9)
-
proc add[T](L: var DoublyLinkedList[T]; value: T)
-
Appends (adds to the end) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- prepend proc for prepending a node
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedList[int]() a.add(9) a.add(8) assert a.contains(9)
-
proc add[T](L: var DoublyLinkedRing[T]; n: DoublyLinkedNode[T])
-
Appends (adds to the end) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a value
- prepend proc for prepending a node
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedRing[int]() let n = newDoublyLinkedNode[int](9) a.add(n) assert a.contains(9)
-
proc add[T](L: var DoublyLinkedRing[T]; value: T)
-
Appends (adds to the end) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- prepend proc for prepending a node
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedRing[int]() a.add(9) a.add(8) assert a.contains(9)
-
proc add[T](L: var SinglyLinkedList[T]; n: SinglyLinkedNode[T]) {.inline.}
-
Appends (adds to the end) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a value
- prepend proc for prepending a node
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedList[int]() let n = newSinglyLinkedNode[int](9) a.add(n) assert a.contains(9)
-
proc add[T](L: var SinglyLinkedList[T]; value: T) {.inline.}
-
Appends (adds to the end) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a value
- prepend proc for prepending a node
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedList[int]() a.add(9) a.add(8) assert a.contains(9)
-
proc add[T](L: var SinglyLinkedRing[T]; n: SinglyLinkedNode[T])
-
Appends (adds to the end) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a value
- prepend proc for prepending a node
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedRing[int]() let n = newSinglyLinkedNode[int](9) a.add(n) assert a.contains(9)
-
proc add[T](L: var SinglyLinkedRing[T]; value: T)
-
Appends (adds to the end) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- prepend proc for prepending a node
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedRing[int]() a.add(9) a.add(8) assert a.contains(9)
-
proc addMoved[T](a, b: var DoublyLinkedList[T])
-
Moves
b
to the end ofa
. Efficiency: O(1). Note thatb
becomes empty after the operation unless it has the same address asa
. Self-adding results in a cycle.See also:
- add proc for adding a copy of a list
Example:
Source Editimport std/[sequtils, enumerate, sugar] var a = [1, 2, 3].toDoublyLinkedList b = [4, 5].toDoublyLinkedList c = [0, 1].toDoublyLinkedList a.addMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] c.addMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1]
-
proc addMoved[T](a, b: var SinglyLinkedList[T])
-
Moves
b
to the end ofa
. Efficiency: O(1). Note thatb
becomes empty after the operation unless it has the same address asa
. Self-adding results in a cycle.See also:
- add proc for adding a copy of a list
Example:
Source Editimport std/[sequtils, enumerate, sugar] var a = [1, 2, 3].toSinglyLinkedList b = [4, 5].toSinglyLinkedList c = [0, 1].toSinglyLinkedList a.addMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] c.addMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1]
-
proc contains[T](L: SomeLinkedCollection[T]; value: T): bool {.inline.}
-
Searches in the list for a value. Returns
false
if the value does not exist,true
otherwise. This allows the usage of thein
andnotin
operators.See also:
Example:
Source Editlet a = [9, 8].toSinglyLinkedList assert a.contains(9) assert 8 in a assert(not a.contains(1)) assert 2 notin a
-
func copy[T](a: DoublyLinkedList[T]): DoublyLinkedList[T]
-
Creates a shallow copy of
a
.Example:
Source Editfrom std/sequtils import toSeq type Foo = ref object x: int var f = Foo(x: 1) a = [f].toDoublyLinkedList let b = a.copy a.add([f].toDoublyLinkedList) assert a.toSeq == [f, f] assert b.toSeq == [f] # b isn't modified... f.x = 42 assert a.head.value.x == 42 assert b.head.value.x == 42 # ... but the elements are not deep copied let c = [1, 2, 3].toDoublyLinkedList assert $c == $c.copy
-
func copy[T](a: SinglyLinkedList[T]): SinglyLinkedList[T]
-
Creates a shallow copy of
a
.Example:
Source Editfrom std/sequtils import toSeq type Foo = ref object x: int var f = Foo(x: 1) a = [f].toSinglyLinkedList let b = a.copy a.add([f].toSinglyLinkedList) assert a.toSeq == [f, f] assert b.toSeq == [f] # b isn't modified... f.x = 42 assert a.head.value.x == 42 assert b.head.value.x == 42 # ... but the elements are not deep copied let c = [1, 2, 3].toSinglyLinkedList assert $c == $c.copy
-
proc prepend[T: SomeLinkedList](a: var T; b: T)
-
Prepends a shallow copy of
b
to the beginning ofa
.See also:
- prependMoved proc for moving the second list instead of copying
Example:
Source Editfrom std/sequtils import toSeq var a = [4, 5].toSinglyLinkedList let b = [1, 2, 3].toSinglyLinkedList a.prepend(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [1, 2, 3] a.prepend(a) assert a.toSeq == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
-
proc prepend[T](L: var DoublyLinkedList[T]; n: DoublyLinkedNode[T])
-
Prepends (adds to the beginning) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedList[int]() let n = newDoublyLinkedNode[int](9) a.prepend(n) assert a.contains(9)
-
proc prepend[T](L: var DoublyLinkedList[T]; value: T)
-
Prepends (adds to the beginning) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a node
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedList[int]() a.prepend(9) a.prepend(8) assert a.contains(9)
-
proc prepend[T](L: var DoublyLinkedRing[T]; n: DoublyLinkedNode[T])
-
Prepends (adds to the beginning) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a value
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedRing[int]() let n = newDoublyLinkedNode[int](9) a.prepend(n) assert a.contains(9)
-
proc prepend[T](L: var DoublyLinkedRing[T]; value: T)
-
Prepends (adds to the beginning) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a node
- remove proc for removing a node
Example:
Source Editvar a = initDoublyLinkedRing[int]() a.prepend(9) a.prepend(8) assert a.contains(9)
-
proc prepend[T](L: var SinglyLinkedList[T]; n: SinglyLinkedNode[T]) {.inline.}
-
Prepends (adds to the beginning) a node to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedList[int]() let n = newSinglyLinkedNode[int](9) a.prepend(n) assert a.contains(9)
-
proc prepend[T](L: var SinglyLinkedList[T]; value: T) {.inline.}
-
Prepends (adds to the beginning) a node to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a node
Example:
Source Editvar a = initSinglyLinkedList[int]() a.prepend(9) a.prepend(8) assert a.contains(9)
-
proc prepend[T](L: var SinglyLinkedRing[T]; n: SinglyLinkedNode[T])
-
Prepends (adds to the beginning) a node
n
toL
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a value
Example:
Source Editvar a = initSinglyLinkedRing[int]() let n = newSinglyLinkedNode[int](9) a.prepend(n) assert a.contains(9)
-
proc prepend[T](L: var SinglyLinkedRing[T]; value: T)
-
Prepends (adds to the beginning) a value to
L
. Efficiency: O(1).See also:
- add proc for appending a node
- add proc for appending a value
- prepend proc for prepending a node
Example:
Source Editvar a = initSinglyLinkedRing[int]() a.prepend(9) a.prepend(8) assert a.contains(9)
-
proc prependMoved[T: SomeLinkedList](a, b: var T)
-
Moves
b
before the head ofa
. Efficiency: O(1). Note thatb
becomes empty after the operation unless it has the same address asa
. Self-prepending results in a cycle.See also:
- prepend proc for prepending a copy of a list
Example:
Source Editimport std/[sequtils, enumerate, sugar] var a = [4, 5].toSinglyLinkedList b = [1, 2, 3].toSinglyLinkedList c = [0, 1].toSinglyLinkedList a.prependMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] c.prependMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1]
-
proc remove[T](L: var DoublyLinkedList[T]; n: DoublyLinkedNode[T])
-
Removes a node
n
fromL
. Efficiency: O(1). This function assumes, for the sake of efficiency, thatn
is contained inL
, otherwise the effects are undefined. When the list is cyclic, the cycle is preserved after removal.Example:
Source Editimport std/[sequtils, enumerate, sugar] var a = [0, 1, 2].toSinglyLinkedList let n = a.head.next assert n.value == 1 a.remove(n) assert a.toSeq == [0, 2] a.remove(n) assert a.toSeq == [0, 2] a.addMoved(a) # cycle: [0, 2, 0, 2, ...] a.remove(a.head) let s = collect: for i, ai in enumerate(a): if i == 4: break ai assert s == [2, 2, 2, 2]
-
proc remove[T](L: var DoublyLinkedRing[T]; n: DoublyLinkedNode[T])
-
Removes
n
fromL
. Efficiency: O(1). This function assumes, for the sake of efficiency, thatn
is contained inL
, otherwise the effects are undefined.Example:
Source Editvar a = initDoublyLinkedRing[int]() let n = newDoublyLinkedNode[int](5) a.add(n) assert 5 in a a.remove(n) assert 5 notin a
-
proc remove[T](L: var SinglyLinkedList[T]; n: SinglyLinkedNode[T]): bool {. discardable.}
-
Removes a node
n
fromL
. Returnstrue
ifn
was found inL
. Efficiency: O(n); the list is traversed untiln
is found. Attempting to remove an element not contained in the list is a no-op. When the list is cyclic, the cycle is preserved after removal.Example:
Source Editimport std/[sequtils, enumerate, sugar] var a = [0, 1, 2].toSinglyLinkedList let n = a.head.next assert n.value == 1 assert a.remove(n) == true assert a.toSeq == [0, 2] assert a.remove(n) == false assert a.toSeq == [0, 2] a.addMoved(a) # cycle: [0, 2, 0, 2, ...] a.remove(a.head) let s = collect: for i, ai in enumerate(a): if i == 4: break ai assert s == [2, 2, 2, 2]
Iterators
-
iterator items[T](L: SomeLinkedList[T]): T
-
Yields every value of
L
.See also:
Example:
Source Editfrom std/sugar import collect from std/sequtils import toSeq let a = collect(initSinglyLinkedList): for i in 1..3: 10 * i assert toSeq(items(a)) == toSeq(a) assert toSeq(a) == @[10, 20, 30]
-
iterator mitems[T](L: var SomeLinkedList[T]): var T
-
Yields every value of
L
so that you can modify it.See also:
Example:
Source Editvar a = initSinglyLinkedList[int]() for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in mitems(a): x = 5 * x - 1 assert $a == "[49, 99, 149, 199, 249]"
-
iterator mitems[T](L: var SomeLinkedRing[T]): var T
-
Yields every value of
L
so that you can modify it.See also:
Example:
Source Editvar a = initSinglyLinkedRing[int]() for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in mitems(a): x = 5 * x - 1 assert $a == "[49, 99, 149, 199, 249]"
-
iterator nodes[T](L: SomeLinkedList[T]): SomeLinkedNode[T]
-
Iterates over every node of
x
. Removing the current node from the list during traversal is supported.See also:
Example:
Source Editvar a = initDoublyLinkedList[int]() for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in nodes(a): if x.value == 30: a.remove(x) else: x.value = 5 * x.value - 1 assert $a == "[49, 99, 199, 249]"
-
iterator nodes[T](L: SomeLinkedRing[T]): SomeLinkedNode[T]
-
Iterates over every node of
x
. Removing the current node from the list during traversal is supported.See also:
Example:
Source Editvar a = initDoublyLinkedRing[int]() for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in nodes(a): if x.value == 30: a.remove(x) else: x.value = 5 * x.value - 1 assert $a == "[49, 99, 199, 249]"
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/lists.html