2022-03-14 10:36:41 +01:00
|
|
|
# nimdeque
|
|
|
|
|
2022-03-15 12:26:09 +01:00
|
|
|
Various deque implementations in pure nim. A deque (short for "double-ended queue") is a data type
|
|
|
|
that is optimized for access towards its ends. A deque's most interesting feauture is the ~O(1)
|
|
|
|
time that it takes to pop/append at either ends (as opposed to regular lists where appending at the
|
|
|
|
beginning is an O(n) operation).
|
|
|
|
|
|
|
|
|
|
|
|
------------------------
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
### LinkedDeque
|
|
|
|
|
2022-03-15 16:34:50 +01:00
|
|
|
A `LinkedDeque` is a deque based on a doubly linked list.
|
2022-03-15 12:26:09 +01:00
|
|
|
|
|
|
|
```nim
|
|
|
|
import nimdeque
|
|
|
|
|
|
|
|
|
|
|
|
queue = newLinkedDeque[int]()
|
|
|
|
|
|
|
|
# Appends at the end
|
|
|
|
queue.add(1)
|
|
|
|
queue.add(2)
|
|
|
|
queue.add(3)
|
|
|
|
|
|
|
|
# Prepends at the beginning
|
|
|
|
queue.addLeft(0)
|
|
|
|
queue.addLeft(-1)
|
|
|
|
queue.addLeft(-2)
|
|
|
|
|
|
|
|
# Pops the first element in O(1) time
|
2022-03-15 16:34:50 +01:00
|
|
|
queue.pop()
|
2022-03-15 12:26:09 +01:00
|
|
|
|
|
|
|
# Pops the last element in O(1) time
|
|
|
|
queue.pop(queue.high())
|
2022-03-15 16:34:50 +01:00
|
|
|
# This can also be written as
|
|
|
|
queue.pop(^1)
|
|
|
|
|
|
|
|
# Pops element at position n
|
|
|
|
queue.pop(n)
|
2022-03-15 12:26:09 +01:00
|
|
|
|
|
|
|
# Supports iteration
|
|
|
|
for i, e in queue:
|
|
|
|
echo i, " ", e
|
|
|
|
|
|
|
|
# Reversed iteration too!
|
|
|
|
for e in queue.reversed():
|
|
|
|
echo e
|
|
|
|
|
|
|
|
echo queue.len()
|
|
|
|
echo 5 in queue # false
|
|
|
|
echo 0 in queue # true
|
|
|
|
|
|
|
|
# Item accessing works just like regular sequence types in Nim.
|
|
|
|
# Note that the further the item is from either end of the
|
|
|
|
# queue, the higher the time it takes to retrieve it. For
|
|
|
|
# fast random access, seqs should be used instead
|
|
|
|
assert queue[0] == -1
|
|
|
|
assert queue[^1] == queue[queue.high()]
|
|
|
|
|
2022-03-15 16:34:50 +01:00
|
|
|
# It's possible to extend a deque with other deques or with seqs
|
|
|
|
# of compatible type
|
|
|
|
var other = newLinkedDeque[int]()
|
|
|
|
other.add(9)
|
|
|
|
other.add(10)
|
|
|
|
queue.extend(@[5, 6, 7, 8])
|
|
|
|
queue.extend(other)
|
2022-03-15 16:57:23 +01:00
|
|
|
|
|
|
|
# Clears the queue in O(1) time
|
|
|
|
queue.clear()
|
|
|
|
# Clears the queue in O(n) time
|
|
|
|
queue.clearPop()
|
2022-03-15 12:26:09 +01:00
|
|
|
```
|
2022-03-14 18:29:12 +01:00
|
|
|
|
2022-03-15 16:34:50 +01:00
|
|
|
---------------------
|
|
|
|
## Notes
|
|
|
|
|
|
|
|
- All queue constructors take an optional `maxSize` argument which limits the size of the queue. The
|
|
|
|
default value is 0 (no size limit). When `maxSize > 0`, the queue will discard elements from the head when
|
|
|
|
items are added at the end and conversely pop items at the end when one is added at the head. Calling `insert`
|
|
|
|
on a full queue will raise an `IndexDefect`
|
|
|
|
- Two deques compare equal if they have the same elements inside them, in the same order. The value of `maxSize` is
|
|
|
|
disregarded in comparisons
|
|
|
|
- Calls to `extend()` **do not** raise any errors when the queue is full. They're merely an abstraction over a for
|
|
|
|
loop calling `self.add()` with every item from the other iterable
|
|
|
|
- Deques in this module do not support slicing. Use the built-in `seq` type if you need fast random accessing and/or slicing
|
|
|
|
capabilities
|
|
|
|
- The objects in this module are **all** tracked references! (Unlike the `std/deques` module which implements them as value
|
|
|
|
types and gives `var` variants of each procedure)
|
|
|
|
|
|
|
|
## Disclaimer
|
|
|
|
|
|
|
|
This is mostly a toy, there are no performance guarantees nor particular optimizations other than very obvious ones. With
|
2022-03-15 17:22:03 +01:00
|
|
|
that said, the collections _do_ work and are tested somewhat thoroughly (please report any bugs!). The tests directory contains
|
|
|
|
some benchmarks as well as the test suite used to validate the behavior of the queues.
|
|
|
|
|
|
|
|
## Why? There's std/deques!
|
|
|
|
|
|
|
|
1. I was bored during my programming class
|
|
|
|
2. That only provides a deque based on `seq`s
|
|
|
|
3. The deque in that module is a value type
|
|
|
|
4. I was bored during my programming class
|
|
|
|
|