summary refs log blame commit diff stats
path: root/lib/pure/collections/lists.nim
blob: 930fd776e2c0b50aa14c8530241d83d8b6241f91 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                                              

                                                                 



                                                  

                                                                 


                                                  






                                                        



































































































































                                                                            
#
#
#            Nimrod's Runtime Library
#        (c) Copyright 2011 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Implementation of singly and doubly linked lists. Because it makes no sense
## to do so, the 'next' and 'prev' pointers are not hidden from you and can
## be manipulated directly for efficiency.

type
  TDoublyLinkedNode*[T] {.pure, 
      final.} = object ## a node a doubly linked list consists of
    next*, prev*: ref TDoublyLinkedNode[T]
    value*: T
  PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T]

  TSinglyLinkedNode*[T] {.pure, 
      final.} = object ## a node a singly linked list consists of
    next*: ref TSinglyLinkedNode[T]
    value*: T
  PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T]
  
  TRingNode[T] {.pure, 
      final.} = object ## a node a ring list consists of
    next*, prev*: ref TRingNode[T]
    value*: T
    
  PRingNode*[T] = ref TRingNode[T]

proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] =
  ## creates a new doubly linked node with the given `value`.
  new(result)
  result.value = value

proc newSinglyLinkedNode*[T](value: T): PSinglyLinkedNode[T] =
  ## creates a new singly linked node with the given `value`.
  new(result)
  result.value = value

iterator items*[T](n: PDoublyLinkedNode[T]): T = 
  ## yields every value of `x`.
  var it = n
  while it != nil:
    yield it.value
    it = it.next

iterator items*[T](n: PSinglyLinkedNode[T]): T = 
  ## yields every value of `x`.
  var it = n
  while it != nil:
    yield it.value
    it = it.next

iterator nodes*[T](n: PSinglyLinkedNode[T]): PSinglyLinkedNode[T] = 
  ## iterates over every node of `x`. Removing the current node from the
  ## list during traversal is supported.
  var it = n
  while it != nil:
    var nxt = it.next
    yield it
    it = nxt

iterator nodes*[T](n: PDoublyLinkedNode[T]): PDoublyLinkedNode[T] = 
  ## iterates over every node of `x`. Removing the current node from the
  ## list during traversal is supported.
  var it = n
  while it != nil:
    var nxt = it.next
    yield it
    it = nxt

proc `$`*[list: PSinglyLinkedNode|PDoublyLinkedNode](n: list): string = 
  ## turns a list into its string representation.
  result = "["
  for x in nodes(n):
    if result.len > 1: result.add(", ")
    result.add($x.value)
  result.add("]")

proc find*[list: PSinglyLinkedNode|PDoublyLinkedNode, T](
           n: list, value: T): list = 
  ## searches in the list for a value. Returns nil if the value does not
  ## exist.
  for x in nodes(n):
    if x.value == value: return x

proc contains*[list: PSinglyLinkedNode|PDoublyLinkedNode, T](
           n: list, value: T): list = 
  ## searches in the list for a value. Returns false if the value does not
  ## exist, true otherwise.
  for x in nodes(n):
    if x.value == value: return true

proc prepend*[T](head: var PSinglyLinkedNode[T], 
                 toAdd: PSinglyLinkedNode[T]) {.inline.} = 
  ## prepends a node to `head`. Efficiency: O(1).
  toAdd.next = head
  head = toAdd

proc prepend*[T](head: var PSinglyLinkedNode[T], x: T) {.inline.} = 
  ## creates a new node with the value `x` and prepends that node to `head`.
  ## Efficiency: O(1).
  preprend(head, newSinglyLinkedNode(x))

proc append*[T](head: var PSinglyLinkedNode[T], 
                toAdd: PSinglyLinkedNode[T]) = 
  ## appends a node to `head`. Efficiency: O(n).
  if head == nil:
    head = toAdd
  else:
    var it = head
    while it.next != nil: it = it.next
    it.next = toAdd

proc append*[T](head: var PSinglyLinkedNode[T], x: T) {.inline.} = 
  ## creates a new node with the value `x` and appends that node to `head`.
  ## Efficiency: O(n).
  append(head, newSinglyLinkedNode(x))


proc prepend*[T](head: var PDoublyLinkedNode[T], 
                 toAdd: PDoublyLinkedNode[T]) {.inline.} = 
  ## prepends a node to `head`. Efficiency: O(1).
  if head == nil:
    head = toAdd
    # head.prev stores the last node:
    head.prev = toAdd
  else:
    toAdd.next = head
    toAdd.prev = head.prev # copy pointer to last element
    head.prev = toAdd
    head = toAdd

proc prepend*[T](head: var PDoublyLinkedNode[T], x: T) {.inline.} = 
  ## creates a new node with the value `x` and prepends that node to `head`.
  ## Efficiency: O(1).
  preprend(head, newDoublyLinkedNode(x))

proc append*[T](head: var PDoublyLinkedNode[T], 
                toAdd: PDoublyLinkedNode[T]) {.inline.} = 
  ## appends a node to `head`. Efficiency: O(1).
  if head == nil:
    head = toAdd
    # head.prev stores the last node:
    head.prev = toAdd
  else:
    var last = head.prev
    assert last.next == nil
    last.next = toAdd
    toAdd.prev = last
    head.prev = toAdd # new last element

proc append*[T](head: var PDoublyLinkedNode[T], x: T) {.inline.} = 
  ## creates a new node with the value `x` and appends that node to `head`.
  ## Efficiency: O(1).
  append(head, newDoublyLinkedNode(x))