From 3d361330b7bed46e14dfe333f724100c789fce0b Mon Sep 17 00:00:00 2001 From: marina <138340846+bt3gl-cryptographer@users.noreply.github.com> Date: Mon, 7 Aug 2023 18:04:47 -0700 Subject: [PATCH] Update README.md --- queues/README.md | 215 +++++++++++++++++++---------------------------- 1 file changed, 87 insertions(+), 128 deletions(-) diff --git a/queues/README.md b/queues/README.md index 18b7fd6..41ead6a 100644 --- a/queues/README.md +++ b/queues/README.md @@ -2,15 +2,15 @@
-* queues are **first in, first out structures (FIFO)** (i.e., items are removed at the same order they are added) that can be implemented with two arrays or a dynamic array (linked list), as long as items are added and removed from opposite sides. +* queues are **first in, first out (FIFO) abstract structures** (*i.e.*, items are removed at the same order they are added) that can be implemented with two arrays or a dynamic array (linked list), as long as items are added and removed from opposite sides. - -* if implemented with a dynamic array, a more efficient solution is to use a circular queue (ring buffer), i.e. a fixed-size array and two pointers to indicate the starting and ending positions. +* queues support **enqueue** (add to the end one end) and **dequeue** (remove from the other end, or tail). + +* if implemented with a dynamic array, a more efficient solution is to use a circular queue (ring buffer), *i.e.*, a fixed-size array and two pointers to indicate the starting and ending positions. * an advantage of circular queues is that we can use the spaces in front of the queue. * in a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. but using the circular queue, we can use the space to store new values. - -* queues are often used in breath-first search (where you store a list of nodes to be processed) or when implementing a cache. +* queues are often used in **breath-first search** (where you store a list of nodes to be processed) or when implementing a cache.
@@ -21,7 +21,16 @@
-* a circular queue can be built with either arrays or linked lists (nodes). to build a ring with a fixed size array, any of the elements could be considered as the head. +* a circular queue can be built with either arrays or linked lists (nodes). + +
+ +#### using arrays + +
+ +* to build a ring with a fixed size array, any of the elements could be considered as the head. + * as long as we know the length of the queue, we can instantly locat its tails based on this formula: ``` @@ -30,12 +39,80 @@ tail_index = (head_index + queue_length - 1) % queue_capacity
-* here is an example of an implementation using a "fixed-sized" array (sort of) using arrays: + +```python +class CircularQueue: + + def __init__(self, k: int): + self.head = 0 + self.tail = 0 + self.size = k + self.queue = [None] * self.size + + def enqueue(self, value: int) -> bool: + + if value is None: + return False + + if self.is_full(): + return False + + if self.is_empty(): + self.heard = 0 + + while self.queue[self.tail] is not None: + self.tail += 1 + if self.tail == self.size: + self.tail = 0 + + self.queue[self.tail] = value + return True + + def dequeue(self) -> bool: + + if self.is_empty(): + return False + + value = self.queue[self.head] + self.queue[self.head] = None + self.head += 1 + + if self.head == self.size: + self.head = 0 + + return True + + def front(self) -> int: + return self.queue[self.head] or -1 + + def rear(self) -> int: + return self.queue[self.tail] or -1 + + def is_empty(self) -> bool: + for n in self.queue: + if n is not None: + return False + return True + + def is_full(self) -> bool: + for n in self.queue: + if n is None: + return False + return True +``` + +
+ +#### using linked lists + +
+ +* note that this queue is not thread-safe: the data structure could be corrupted in a multi-threaded environment (as race-condition could occur). to mitigate this problem, one could add the protection of a lock.
```python -class CircularQueue: + class CircularQueue: def __init__(self, k: int): self.head = -1 @@ -46,8 +123,7 @@ class CircularQueue: def _get_next_position(self, end) -> int: return (end + 1) % self.size - def enQueue(self, value: int) -> bool: - + def enqueue(self, value: int) -> bool: if self.is_full(): return False @@ -56,11 +132,9 @@ class CircularQueue: self.tail = self._get_next_position(self.tail) self.queue[self.tail] = value - return True - def deQueue(self) -> bool: - + def dequeue(self) -> bool: if self.is_empty(): return False @@ -70,7 +144,6 @@ class CircularQueue: return True self.head = self._get_next_position(self.head) - return True def front(self) -> int: @@ -90,121 +163,7 @@ class CircularQueue: return self._get_next_position(self.tail) == self.head ``` -
- -* and here is a much clear example using a linked list:
-```python -class Node: - def __init__(self, value, next=None): - self.value = value - self.next = next - - -class CircularQueue: - - def __init__(self, k: int): - - self.capacity = k - self.count = 0 - self.head = None - self.tail = None - - def enqueue(self, value: int) -> bool: - - if self.count == self.capacity: - return False - - if self.count == 0: - self.head = Node(value) - self.tail = self.head - else: - new_node = Node(value) - self.tail.next = new_node - self.tail = new_node - - self.count += 1 - - return True - - def dequeue(self) -> bool: - - if self.count == 0: - return False - - self.head = self.head.next - self.count -= 1 - - return True - - def front(self) -> int: - - if self.count == 0: - return -1 - - return self.head.value - - def rear(self) -> int: - - if self.count == 0: - return -1 - - return self.tail.value - - def is_empty(self) -> bool: - - return self.count == 0 - - def is_full(self) -> bool: - - return self.count == self.capacity -``` - - -
- -* note that this queue is not thread-safe: the data structure could be corrupted in a multi-threaded environment (as race-condition could occur). to mitigate this problem, one could add the protection of a lock. - - -
- ----- - -### some examples in this directory - -
- -#### `queues.py` - -
- -```python -> python3 queues.py - -🧪 Testing Queue... -Is the queue empty? True -Adding 1 to 10 in the queue... -Queue: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] - -Queue size: 10 -Queue peek : 1 -Is the queue empty? False - -Dequeue... -Queue: [10, 9, 8, 7, 6, 5, 4, 3, 2] - -Queue size: 9 -Queue peek: 2 -Is the queue empty? False - - -🧪 Testing Priority Queue... -Priority Queue: [(-4, 1, Item 4), (-1, 0, Item 1), (-3, 2, Item 3)] -Pop: Item 4 -Priority Queue: [(-3, 2, Item 3), (-1, 0, Item 1)] -``` - -