Reputation: 409
class MyQueue:
def __init__(self, size):
self.q = [None] * size # list to store queue elements
self.capacity = size # maximum capacity of the queue
self.front = 0 # front points to the front element in the queue
self.rear = -1 # rear points to the last element in the queue
self.count = 0 # current size of the queue
def pop(self):
if self.is_empty():
print("Queue Underflow!! Terminating process.")
exit(1)
print("Removing element…", self.q[self.front])
self.front = (self.front + 1) % self.capacity
self.count = self.count - 1
def append(self, value):
if self.is_full():
print("Queue is full! Terminating process.")
exit(1)
print("Inserting element…", value)
self.rear = (self.rear + 1) % self.capacity
self.q[self.rear] = value
self.count = self.count + 1
def peek(self):
if self.is_empty():
print("Queue is empty!! Terminating process.")
exit(1)
return self.q[self.front]
def size(self):
return self.count
def is_empty(self):
return self.size() == 0
def is_full(self):
return self.size() == self.capacity
So I am currently learning Python and came across this example of a Stack data structure implemented using a class and some functions.
The problem I have is that I do not understand what the modulo operator is being used for here. As far as I can tell, Modulo is used to calculate te remainder, so in this example why do we need it for a queue?
Shouldn't it just be we want to add something to the front - so we take one away from the current front counter and add it there?
Upvotes: 0
Views: 141
Reputation: 4731
It's also called a deque(double ended queue) or circular queue. The terms front
and rear
in that code are inadequate. head
and tail
are more adequate. When the queue is empty, the head is equal to the tail. When you push into the queue, the tail is increased usually. When you pop from the queue, the head is increased usually. When the head or tail reaches the end of the buffer, it is rewound to the start of the buffer. When the queue is full, the tail is just behind the head usually.
In a circular queue, you don't need to shift elements while popping elements like a stack.(If you implement a naive queue with a list, list.pop(0)
results in shifting elements and that's O(N).)
Using a modulo operator for calculating a head or tail index is a trick to rewind an index.
tail = (tail + 1) % N
# The above one line is equivalent to the following.
tail = tail + 1
if tail >= N:
tail = 0
It's implemented as the collections.deque in the standard library.
Upvotes: 1