From 68452cff76f5ccec489d15a075e5c62e9106622a Mon Sep 17 00:00:00 2001 From: Hunam Date: Thu, 23 Dec 2021 17:57:15 +0100 Subject: [PATCH] adt: add queue (#12941) --- vlib/adt/README.md | 27 +++++++++++++++++++----- vlib/adt/queue.v | 36 +++++++++++++++++++++++++++++++ vlib/adt/queue_test.v | 49 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 vlib/adt/queue.v create mode 100644 vlib/adt/queue_test.v diff --git a/vlib/adt/README.md b/vlib/adt/README.md index 92903eeb46..55293404b7 100644 --- a/vlib/adt/README.md +++ b/vlib/adt/README.md @@ -1,10 +1,27 @@ -# adt +# datatypes -A library providing common ADTs (Abstract Data Type) implementations which have proved useful in a -great variety of applications. +This module provides implementations of less frequently used, but still common +data types. -## implementations +V's `builtin` module is imported implicitly, and has implementations for arrays, +maps and strings. These are good for many applications, but there are a plethora +of other useful data structures/containers, like linked lists, priority queues, +tries, etc, that allow for algorithms with different time complexities, which may +be more suitable for your specific application. + +It is implemented using generics, that you have to specialise for the type of +your actual elements. For example: +```v +import adt + +mut stack := adt.Stack{} +stack.push(1) +println(stack) +``` + +## Currently Implemented Datatypes: -- [x] Stack (LIFO) - [x] Linked list +- [x] Stack (LIFO) +- [x] Queue (FIFO) - [ ] ... diff --git a/vlib/adt/queue.v b/vlib/adt/queue.v new file mode 100644 index 0000000000..bda51c55eb --- /dev/null +++ b/vlib/adt/queue.v @@ -0,0 +1,36 @@ +module adt + +pub struct Queue { +mut: + elements LinkedList +} + +// is_empty checks if the queue is empty +pub fn (queue Queue) is_empty() bool { + return queue.elements.is_empty() +} + +// len returns the length of the queue +pub fn (queue Queue) len() int { + return queue.elements.len() +} + +// peek returns the head of the queue +pub fn (queue Queue) peek() ?T { + return if !queue.is_empty() { queue.elements.first() ? } else { error('Queue is empty') } +} + +// push adds an element to the tail of the queue +pub fn (mut queue Queue) push(item T) { + queue.elements.push(item) +} + +// pop removes the element at the head of the queue and returns it +pub fn (mut queue Queue) pop() ?T { + return if !queue.is_empty() { queue.elements.shift() ? } else { error('Queue is empty') } +} + +// str returns a string representation of the queue +pub fn (queue Queue) str() string { + return queue.elements.str() +} diff --git a/vlib/adt/queue_test.v b/vlib/adt/queue_test.v new file mode 100644 index 0000000000..499a2a192a --- /dev/null +++ b/vlib/adt/queue_test.v @@ -0,0 +1,49 @@ +module adt + +fn test_is_empty() { + mut queue := Queue{} + assert queue.is_empty() == true + queue.push(1) + assert queue.is_empty() == false +} + +fn test_len() ? { + mut queue := Queue{} + assert queue.len() == 0 + queue.push(1) + assert queue.len() == 1 + queue.pop() ? + assert queue.len() == 0 +} + +fn test_peek() ? { + mut queue := Queue{} + queue.push(1) + assert queue.peek() ? == 1 + queue.push(2) + assert queue.peek() ? == 1 + queue = Queue{} + queue.peek() or { return } + assert false +} + +fn test_push() ? { + mut queue := Queue{} + queue.push(1) + queue.push(2) + assert queue.peek() ? == 1 +} + +fn test_pop() ? { + mut queue := Queue{} + queue.push(1) + queue.push(2) + queue.push(3) + assert queue.pop() ? == 1 + queue.push(4) + assert queue.pop() ? == 2 + assert queue.pop() ? == 3 + queue = Queue{} + queue.pop() or { return } + assert false +}