Fixed pop() at the end, added random insertion test, added BackwardsIndex support
This commit is contained in:
parent
4dfefba043
commit
36cced8ff1
|
@ -1,3 +1,7 @@
|
|||
# nimdeque
|
||||
|
||||
Various deque implementations in pure nim
|
||||
Various deque implementations in pure nim. See the tests directory for usage examples
|
||||
|
||||
|
||||
__Note__: This is mostly a toy, there are no performance guarantees nor particular optimizations other than very obvious ones. With
|
||||
that said, the collections _do_ work and are tested somewhat thoroughly (please report any bugs!)
|
||||
|
|
|
@ -113,7 +113,6 @@ proc getNode[T](self: LinkedDeque[T], i: int): DequeNode[T] =
|
|||
dec(pos)
|
||||
|
||||
|
||||
|
||||
proc insert*[T](self: LinkedDeque[T], pos: int, val: T) =
|
||||
## Inserts the given value at the given
|
||||
## position. When pos equals 0 or self.high(),
|
||||
|
@ -121,7 +120,9 @@ proc insert*[T](self: LinkedDeque[T], pos: int, val: T) =
|
|||
## respectively. In all other cases, all items
|
||||
## are "shifted" by 1 (shifted is in quotes because
|
||||
## no shifting actually occurs, but the result is
|
||||
## the same). The operation takes constant time
|
||||
## the same). The operation takes roughly constant
|
||||
## time and the complexity becomes O(n) the closer
|
||||
## the index gets to the middle of the deque
|
||||
if pos == 0:
|
||||
self.addLeft(val)
|
||||
elif pos == self.high():
|
||||
|
@ -137,7 +138,6 @@ proc insert*[T](self: LinkedDeque[T], pos: int, val: T) =
|
|||
inc(self.size)
|
||||
|
||||
|
||||
|
||||
proc `[]`*[T](self: LinkedDeque[T], i: int): T =
|
||||
## Implements indexing into the queue
|
||||
result = self.getNode(i).val
|
||||
|
@ -149,6 +149,18 @@ proc `[]=`*[T](self: LinkedDeque[T], i: int, val: T) =
|
|||
self[i].val = val
|
||||
|
||||
|
||||
proc `[]`*[T](self: LinkedDeque[T], i: BackwardsIndex): T =
|
||||
## Implements indexing into the queue
|
||||
## with backwards indeces
|
||||
result = self[self.size - int(i)]
|
||||
|
||||
|
||||
proc `[]=`*[T](self: LinkedDeque[T], i: BackwardsIndex, val: T) =
|
||||
## Sets element at backwards
|
||||
## position i to the given value
|
||||
self[self.size - int(i)] = val
|
||||
|
||||
|
||||
proc pop*[T](self: LinkedDeque[T], pos: int = 0): T =
|
||||
## Pops an element off the queue
|
||||
## at the given index (default 0).
|
||||
|
@ -161,13 +173,23 @@ proc pop*[T](self: LinkedDeque[T], pos: int = 0): T =
|
|||
if pos == 0:
|
||||
self.head = self.head.next
|
||||
elif pos == self.high():
|
||||
self.tail = self.tail.prev
|
||||
var prev = self.tail.prev
|
||||
prev.next = nil
|
||||
self.tail = prev
|
||||
else:
|
||||
node.prev.next = node.next
|
||||
var prev = node.prev
|
||||
var next = node.next
|
||||
prev.next = node.next
|
||||
next.prev = prev
|
||||
result = node.val
|
||||
dec(self.size)
|
||||
|
||||
|
||||
proc pop*[T](self: LinkedDeque[T], i: BackwardsIndex): T =
|
||||
## Same as self.pop but for backwards indeces
|
||||
result = self.pop(self.size - int(i) - 1)
|
||||
|
||||
|
||||
iterator items*[T](self: LinkedDeque[T]): T =
|
||||
## Implements the iteration protocol
|
||||
## for the queue
|
||||
|
@ -212,6 +234,6 @@ proc `$`*[T](self: LinkedDeque[T]): string =
|
|||
result = "deque(["
|
||||
for i, item in self:
|
||||
result &= $item
|
||||
if i < self.len():
|
||||
if i < self.high():
|
||||
result &= ", "
|
||||
result &= "])"
|
|
@ -11,6 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import random
|
||||
import strformat
|
||||
import ../src/nimdeque
|
||||
|
||||
|
@ -19,65 +20,79 @@ when isMainModule:
|
|||
const size = 1000
|
||||
var deque = newLinkedDeque[int]()
|
||||
echo &"Generating {size} values"
|
||||
for i in countup(0, size, 1):
|
||||
for i in countup(0, size - 1, 1):
|
||||
deque.add(i)
|
||||
echo "Checking length"
|
||||
doAssert deque.len() == size + 1
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == size
|
||||
echo "Checking iteration"
|
||||
for i in countup(0, size, 1):
|
||||
for i in countup(0, size - 1, 1):
|
||||
doAssert deque[i] == i
|
||||
echo "Checking contains"
|
||||
for i in countup(0, size, 1):
|
||||
for i in countup(0, size - 1, 1):
|
||||
doAssert i in deque
|
||||
echo "Popping off the head"
|
||||
doAssert deque.pop() == 0
|
||||
echo "Checking length"
|
||||
doAssert deque.len() == size
|
||||
echo "Popping off the tail"
|
||||
doAssert deque.pop(deque.high()) == size
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == size - 1
|
||||
echo "\t- Popping off the tail"
|
||||
doAssert deque.pop(deque.high()) == size - 1
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == size - 2
|
||||
echo "Checking new head"
|
||||
doAssert deque[0] == 1
|
||||
echo "Checking new tail"
|
||||
doAssert deque[deque.high()] == size - 1
|
||||
doAssert deque[deque.high()] == size - 2
|
||||
echo "Re-checking values"
|
||||
for i in countup(0, size - 2, 1):
|
||||
for i in countup(0, size - 3, 1):
|
||||
doAssert deque[i] == i + 1
|
||||
echo "Checking addLeft"
|
||||
deque.addLeft(0)
|
||||
echo "Checking length"
|
||||
doAssert deque.len() == size
|
||||
echo "Re-checking head"
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == size - 1
|
||||
echo "\t- Re-checking head"
|
||||
doAssert deque[0] == 0
|
||||
echo "Re-checking values"
|
||||
for i in countup(0, size - 1, 1):
|
||||
for i in countup(0, size - 2, 1):
|
||||
doAssert deque[i] == i
|
||||
echo "Checking insert(3)"
|
||||
var oldLen = deque.len()
|
||||
deque.insert(3, 69420)
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert oldLen + 1 == deque.len()
|
||||
echo "Checking inserted value"
|
||||
echo "\t- Checking inserted value"
|
||||
doAssert deque.pop(3) == 69420
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == oldLen
|
||||
echo &"Checking insert({size - 2})"
|
||||
oldLen = deque.len()
|
||||
deque.insert(size - 2, 0x42362)
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert oldLen + 1 == deque.len()
|
||||
echo "Checking inserted value"
|
||||
doAssert deque.pop(size - 2) == 0x42362
|
||||
echo "Checking length"
|
||||
echo "\t- Checking inserted value"
|
||||
doAssert deque.pop(size - 1) == 0x42362
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == oldLen
|
||||
echo &"Checking insert({size div 2})"
|
||||
oldLen = deque.len()
|
||||
deque.insert(size div 2, 0xf7102)
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert oldLen + 1 == deque.len()
|
||||
echo "Checking inserted value"
|
||||
echo "\t- Checking inserted value"
|
||||
doAssert deque.pop(size div 2) == 0xf7102
|
||||
echo "Checking length"
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == oldLen
|
||||
randomize()
|
||||
let idx = rand(size - 1)
|
||||
echo &"Checking insert({idx})"
|
||||
oldLen = deque.len()
|
||||
deque.insert(size - 2, idx)
|
||||
echo "\t- Checking length"
|
||||
doAssert oldLen + 1 == deque.len()
|
||||
echo "\t- Checking inserted value"
|
||||
doAssert deque.pop(size - 1) == idx
|
||||
echo "\t- Checking length"
|
||||
doAssert deque.len() == oldLen
|
||||
echo "Checking backwards indeces"
|
||||
for i in countdown(deque.high(), 1):
|
||||
doAssert deque[^i] == deque[deque.len() - i]
|
||||
echo "All tests passed!"
|
||||
|
|
Loading…
Reference in New Issue