Skip to content

Commit 70368a7

Browse files
bit-manpoyea
andauthored
Implement Circular Queue using linked lists. Fixes TheAlgorithms#5361 (TheAlgorithms#5587)
* CircularQueueLinkedList: empty list, trivial implementation TheAlgorithms#5361 * CircularQueueLinkedList: single element list TheAlgorithms#5361 * CircularQueueLinkedList: refactor, no que empty attribute TheAlgorithms#5361 * CircularQueueLinkedList: refactor TheAlgorithms#5361 * CircularQueueLinkedList: changed internal data structure to use double linked list TheAlgorithms#5361 * CircularQueueLinkedList: enqueue test cases added TheAlgorithms#5361 * CircularQueueLinkedList: track full queue TheAlgorithms#5361 * CircularQueueLinkedList: adding functions description TheAlgorithms#5361 * CircularQueueLinkedList: type hints TheAlgorithms#5361 * CircularQueueLinkedList: algorithm explanation TheAlgorithms#5361 * CircularQueueLinkedList: missing type hints TheAlgorithms#5361 * CircularQueueLinkedList: more missing type hints TheAlgorithms#5361 * Update data_structures/queue/circular_queue_linked_list.py Co-authored-by: John Law <[email protected]>
1 parent bf6db32 commit 70368a7

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Implementation of Circular Queue using linked lists
2+
# https://en.wikipedia.org/wiki/Circular_buffer
3+
4+
from typing import Any
5+
6+
7+
class CircularQueueLinkedList:
8+
"""
9+
Circular FIFO list with the given capacity (default queue length : 6)
10+
11+
>>> cq = CircularQueueLinkedList(2)
12+
>>> cq.enqueue('a')
13+
>>> cq.enqueue('b')
14+
>>> cq.enqueue('c')
15+
Traceback (most recent call last):
16+
...
17+
Exception: Full Queue
18+
"""
19+
20+
def __init__(self, initial_capacity: int = 6) -> None:
21+
self.front = None
22+
self.rear = None
23+
self.create_linked_list(initial_capacity)
24+
25+
def create_linked_list(self, initial_capacity: int) -> None:
26+
current_node = Node()
27+
self.front = current_node
28+
self.rear = current_node
29+
previous_node = current_node
30+
for i in range(1, initial_capacity):
31+
current_node = Node()
32+
previous_node.next = current_node
33+
current_node.prev = previous_node
34+
previous_node = current_node
35+
previous_node.next = self.front
36+
self.front.prev = previous_node
37+
38+
def is_empty(self) -> bool:
39+
"""
40+
Checks where the queue is empty or not
41+
>>> cq = CircularQueueLinkedList()
42+
>>> cq.is_empty()
43+
True
44+
>>> cq.enqueue('a')
45+
>>> cq.is_empty()
46+
False
47+
>>> cq.dequeue()
48+
'a'
49+
>>> cq.is_empty()
50+
True
51+
"""
52+
return self.front == self.rear and self.front.data is None
53+
54+
def first(self) -> Any:
55+
"""
56+
Returns the first element of the queue
57+
>>> cq = CircularQueueLinkedList()
58+
>>> cq.first()
59+
Traceback (most recent call last):
60+
...
61+
Exception: Empty Queue
62+
>>> cq.enqueue('a')
63+
>>> cq.first()
64+
'a'
65+
>>> cq.dequeue()
66+
'a'
67+
>>> cq.first()
68+
Traceback (most recent call last):
69+
...
70+
Exception: Empty Queue
71+
>>> cq.enqueue('b')
72+
>>> cq.enqueue('c')
73+
>>> cq.first()
74+
'b'
75+
"""
76+
self.check_can_perform_operation()
77+
return self.front.data
78+
79+
def enqueue(self, data: Any) -> None:
80+
"""
81+
Saves data at the end of the queue
82+
83+
>>> cq = CircularQueueLinkedList()
84+
>>> cq.enqueue('a')
85+
>>> cq.enqueue('b')
86+
>>> cq.dequeue()
87+
'a'
88+
>>> cq.dequeue()
89+
'b'
90+
>>> cq.dequeue()
91+
Traceback (most recent call last):
92+
...
93+
Exception: Empty Queue
94+
"""
95+
self.check_is_full()
96+
if self.is_empty():
97+
self.rear.data = data
98+
else:
99+
self.rear = self.rear.next
100+
self.rear.data = data
101+
102+
def dequeue(self) -> Any:
103+
"""
104+
Removes and retrieves the first element of the queue
105+
106+
>>> cq = CircularQueueLinkedList()
107+
>>> cq.dequeue()
108+
Traceback (most recent call last):
109+
...
110+
Exception: Empty Queue
111+
>>> cq.enqueue('a')
112+
>>> cq.dequeue()
113+
'a'
114+
>>> cq.dequeue()
115+
Traceback (most recent call last):
116+
...
117+
Exception: Empty Queue
118+
"""
119+
self.check_can_perform_operation()
120+
if self.front == self.rear:
121+
data = self.front.data
122+
self.front.data = None
123+
return data
124+
125+
old_front = self.front
126+
self.front = old_front.next
127+
data = old_front.data
128+
old_front.data = None
129+
return data
130+
131+
def check_can_perform_operation(self) -> None:
132+
if self.is_empty():
133+
raise Exception("Empty Queue")
134+
135+
def check_is_full(self) -> None:
136+
if self.rear.next == self.front:
137+
raise Exception("Full Queue")
138+
139+
140+
class Node:
141+
def __init__(self) -> None:
142+
self.data = None
143+
self.next = None
144+
self.prev = None
145+
146+
147+
if __name__ == "__main__":
148+
import doctest
149+
150+
doctest.testmod()

0 commit comments

Comments
 (0)