I am trying to implement Circular Queue in python and trying implement str(self) that print all the elements from the queue from the beginning to the end.When I print out the list, it does not give the whole list of items in the queue.
I am splicing the items from the self.items from the front and going till the end of the list.
class CircularQueue:
def __init__(self,capacity):
self.items =[None]*capacity
self.MAX_QUEUE = capacity
self.front = 0
self.back = self.MAX_QUEUE - 1
self.count = 0
def is_full(self):
return self.count == self.MAX_QUEUE
def is_empty(self):
return self.count == 0
def enqueue(self,item):
if not self.is_full():
self.back = (self.back+1)%self.MAX_QUEUE
self.items[self.back] = item
self.count +=1
else:
raise IndexError("The queue is full.")
def dequeue(self):
if not self.is_empty():
item = self.items[self.front]
self.front =(self.front+1)% self.MAX_QUEUE
self.count -=1
return item
else:
raise IndexError("The queue is empty.")
def peek(self):
if not self.is_empty():
item = self.items[self.front]
return item
else:
raise IndexError("The queue is empty.")
def __str__(self):
my_list = []
for i in self.items[self.front:]:
my_list.append(i)
return str(my_list)
q = CircularQueue(8)
q.enqueue(5)
q.enqueue(2)
q.enqueue(1)
q.enqueue(7)
q.enqueue(9)
q.dequeue()
q.dequeue()
q.dequeue()
q.dequeue()
q.dequeue()
q.enqueue(2)
q.enqueue(4)
q.enqueue(1)
q.enqueue(7)
q.enqueue(6)
q.enqueue(3)
print(q)
Expected result:
[2, 4, 1, 7, 6, 3]
Got:
[2,4,1]
It looks like your problem is that you only add in the elements from the front of the circular array to the end of the underlying list implementation. What you really want to do is copy from front to end, and then from beginning to back.
This gives me the correct output
def __str__(self):
my_list = []
for i in self.items[self.front:]:
my_list.append(i)
for i in self.items[:self.back+1]:
my_list.append(i)
return str(my_list)
Hope that helps! Also, you might want to consider using cycle from itertools.
Related
I am trying to implement Circular Queue in python and trying implement str(self) that print all the elements from the queue from the beginning to the end.When I print out the list, it does not give the whole list of items in the queue.
I am splicing the items from the self.items from the front and going till the end of the list.
class CircularQueue:
def __init__(self, capacity):
self.items = [None] * capacity
self.max_queue = capacity
self.front = 0
self.back = self.max_queue - 1
self.count = 0
def enqueue(self, item):
if not self.is_full():
self.back = (self.back + 1) % self.max_queue
self.items[self.back] = item
self.count += 1
def dequeue(self):
if not self.is_empty():
item = self.items[self.front]
self.front = (self.front + 1) % self.max_queue
self.count -= 1
return item
def is_full(self):
return self.count == self.max_queue
def is_empty(self):
return self.count == 0
def peek(self):
return self.items[self.front]
def __str__(self):
my_list = []
for i in self.items[self.front:]:
my_list.append(i)
for i in self.items[:self.back+1]:
my_list.append(i)
return str(my_list)
q = CircularQueue(4)
print(q)
q.enqueue(1)
q.enqueue(2)
print(q)
q.enqueue(3)
q.enqueue(4)
print(q)
expected result
-> || ->
-> |1, 2| ->
-> |1, 2, 3, 4| ->
got
[None, None, None, None, None, None, None, None]
[1, 2, None, None, 1, 2]
[1, 2, 3, 4, 1, 2, 3, 4]
q = CircularQueue(4)
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
q.enqueue(4)
q.dequeue()
q.dequeue()
print(q)
q.dequeue()
q.dequeue()
print(q)
expected result
-> |3, 4| ->
-> || ->
got
[3, 4, 1, 2, 3, 4]
[1, 2, 3, 4, 1, 2, 3, 4]
You added two similar for loops, it's just that the first for loop prints everything on the right of the front, and the second for loop prints everything on the left of the back/rear. For example, if we have [1,2,None,None] where the front is at index 0 (value=1) and the rear is at index 1 (value=2) the 2 loops will print out [1,2,None,None,1,2], p.s the code adds 1 to the rear when printing, that's why you get [1,2,None,None,1,2] and not [1,2,None,None,1]
Solution:
replace the 2 for loops with 1 for loop that goes through the elements of the list once, so no splicing is needed
For the second output, I noticed that the dequeue function doesn't do anything, so I made it so that it replaces the item in the front with None
I added # changed on the lines I changed
class CircularQueue:
def __init__(self, capacity):
self.items = [None] * capacity
self.max_queue = capacity
self.front = 0
self.back = self.max_queue - 1
self.count = 0
def enqueue(self, item):
if not self.is_full():
self.back = (self.back + 1) % self.max_queue
self.items[self.back] = item
self.count += 1
def dequeue(self):
if not self.is_empty():
self.items[self.front] = None # changed
self.front = (self.front + 1) % self.max_queue
self.count -= 1
def is_full(self):
return self.count == self.max_queue
def is_empty(self):
return self.count == 0
def peek(self):
return self.items[self.front]
def __str__(self):
my_list = []
for i in self.items: # changed
my_list.append(i)
return str(my_list)
I am studying book 'Data Structure and algorithms in python' by M. Goodrich and was looking dequeue implementation in queue class, please see below:
class Queue:
DEFAULT_CAPACITY = 10
def __init__(self):
self._data = [None] * Queue.DEFAULT_CAPACITY
self._size = 0 # queue current size
self._front = 0
def __len__(self):
return self._size
def is_empty(self):
return self._size == 0
def enqueue(self, dt):
if self._size == len(self._data):
self._resize(2 * len(self._data))
empty = (self._front + self._size) % len(self._data)
self._data[empty] = dt
self._size += 1
def first(self):
if self.is_empty():
raise QueueisEmpty
return self._data[self._front]
def dequeue(self):
if self.is_empty():
raise QueueisEmpty("Queue is empty")
answer = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1) % len(self._data)
self._size -= 1
return ret
def _resize(self, desired_size):
old = self._data
walk = self._front
self._data = [None] * desired_size
for i in range(self._size):
self._data[i] = old[walk]
walk = (1 + walk) % len(old)
self._front = 0
class QueueisEmpty(BaseException):
pass
if you look dequeue method you will see that it checks that queue is not empty then get a reference to the first element by
answer = self._data[self._front]
I am curious why the author is not used built-in self.first() method instead.
This way it will have two benefits in my opinion:
it will have a shorter code
it will take care of empty queue cases
class Queue:
def __init__(self): '''initialization of function'''
self.items = []
def is_empty(self): '''Checking if queue is empty or not'''
return self.items == []
def enqueue(self, data): '''Adding value '''
self.items.append(data)
def dequeue(self): ''' Removing value'''
return self.items.pop(0)
def dis(self): '''Printing the stored item in queue'''
print(items)
After that initialization of Queue:
q = Queue()
while True:
print('enqueue <value>')
print('dequeue')
print('dis')
print('quit')
do = input('What would you like to do? ').split()
operation = do[0].strip().lower()
if operation == 'enqueue':
q.enqueue(int(do[1]))
elif operation == 'dequeue':
if q.is_empty():
print('Queue is empty.')
else:
print('Dequeued value: ', q.dequeue())
elif operation == 'dis':
q.dis()
elif operation == 'quit':
break
else:
print("Enter the correct operation")
I'm not able to display the items which are enqueued in the Queue. How could I use dis() method to display items in it?
Think you should print self.items (instead of items)
def dis(self): '''Printing the stored item in queue'''
print(self.items)
That'll output the list using standard formatting, not very pretty so you'll probably want to add some extra logic for pretty-printing.
If you want to restrict the queue size, you could do this by simply ignoring items past a certain limit. For this you'll need to implement a limit, along with logic for checking the limit. For example:
class Queue:
def __init__(self, size=8): '''initialization of function'''
self.items = []
self.size = size
def is_empty(self): '''Checking if queue is empty or not'''
return self.items == []
def enqueue(self, data): '''Adding value '''
if len(self.items) < self.size:
self.items.append(data)
else:
pass # behavior when queue is already full
def dequeue(self): ''' Removing value'''
return self.items.pop(0)
def dis(self): '''Printing the stored item in queue'''
print(items)
class Queue:
items=[]
size=5
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def enqueue(self, data):
self.items.append(data)
def dequeue(self):
return self.items.pop(0)
def dis(self):
print(self.items)
def is_full(self):
if (len(self.zitems)>5):
print("Queue is full")
else:
print("Not full")
Inizialize the items=[] and in dis method add self.items.Also, you could check if the size of the queue is full or not
So this is my "completed" code for my homework assignment which was to modify a program to remove an item from a list and add it to the back of the queue.
I went from Java to Python so I am still having trouble understanding and learning the proper syntax and formatting. I have an error on Line 41 where it keeps saying invalid syntax. What would be a better way to rewrite this? (I will put a comment next to the exact line in the code) Also any formatting help would be deeply appreciated (is there a better way to write a loop, is there too much redundancy, etc), I'm trying my best!
My Code:
class Queue():
def __init__(self):
self.items = [None] * 10
self.size_ = 0
self.front = 0
self.rear = -1
def size(self):
return self.size_
def isEmpty(self):
return self.size_ == 0
def peek(self):
if self.isEmpty():
raise Empty('Queue is empty')
return self.items[self.front]
def enqueue(self,item):
self.addRear(item)
def dequeue(self):
return self.removeFront()
def addRear(self, item):
if self.size_ == len(self.items):
self.resize(2 * len(self.items))
avail = (self.rear + 1) % len(self.items)
self.items[avail] = item
self.rear = self.rear + 1
self.size_ += 1
def addFront(self,item):
if self.size_ == len(self.items):
self.resize(2*len(self.items))
avail = 0
if self.front == 0:
if self.rear == -1:
self.rear = 0
avail = 0
else:
avail = len(self.items) - 1
else: #################
########## Syntax error is here!! Should I rewrite the above as a while loop and then make this into an elif?
avail = (self.front - 1) % len(self.items)
self.items[avail] = item
self.front = avail
self.size_ += 1
def removeFront(self):
if self.isEmpty():
raise Empty('Queue is empty')
answer = self.items[self.front]
self.items[self.front] = None
self.front = (self.front + 1) % len(self.items)
self.size_ -= 1
return answer
def removeRear(self):
if self.isEmpty():
raise Empty('Queue is empty')
answer = self.items[self.rear]
self.items[self.rear] = None
if self.rear == 0:
self.rear = len(self.items) - 1
else:
self.rear = (self.rear - 1) % len(self.items)
self.size_ -= 1
return answer
def resize(self, cap):
old = self.items
self.items = [None] * cap
walk = self.front
for k in range(self.size_):
self.items[k] = old[walk]
walk = (1 + walk) % len(old)
self.front = 0
self.rear = self.size_ - 1
q = Queue()
q.isEmpty()
q.addFront (100)
print(q.size())
q.addFront (200)
q.addFront (500.58)
print(q.size())
print(q.peek()) # print the front item of the queue
q.addRear(500)
q.addRear(600)
q.addFront(3.14)
print(q.size())
print(q.peek()) # print the front item of the queue
q.removeFront()
print(q.size())
print(q.peek()) # print the front item of the queue
q.addRear("True")
q.addRear("False")
print(q.size())
q.isEmpty()
q.addRear(8.4)
q.removeRear()
print(q.size())
print(q.peek()) # print the front item of the queue
q.addRear("C++")
q.addRear("Python")
q.addRear("Java")
print(q.size())
q.addFront ("Go")
q.addFront ("C")
print(q.size())
print(q.dequeue())
q.removeFront()
q.removeFront()
print (q.size())
Okay! If I'm not being specific enough, just let me know. I'm here to learn so anyone who is a master at Python please teach me the art of efficient Python code!
I don't think I can help with editing you code, but the error in you code is that the else: isnt picking any if argument as they are stopped/interrupted by the avail=0 assignment.
If you want to add an item behind a list, you can just use:
li = ['front', 'mid', 'back'] + ['newBack']
whick outputs:
['front', 'mid', 'back', 'newBack']
if you want to add in front, just:
li = ['newFront'] + ['front', 'mid', 'back']
which outputs:
['newFront', 'front', 'mid', 'back']
if you want to remove the first item, you can:
li = ['newFront', 'front', 'mid', 'back']
removed = li.pop(0)
where the resulting values would be:
li = ['front', 'mid', 'back']
removed = 'newFront'
note: list.pop(index) is a method that removes the item in the index in the indicated list and returns it, if no index value is inserted, it will remove the last item in the list. pop is useful for queue management.
I am trying to modify the class so the capacity automatically increases when I exceed the current capacity. When trying to add to a full queue, the capacity doubles.
I have created a new list with twice the original capacity.Enqueue the items from the original list onto the new list keeping track of the new front and back.
class CircularQueue:
def __init__(self,capacity):
self.items =[None]*capacity
self.MAX_QUEUE = capacity
self.front = 0
self.back = self.MAX_QUEUE - 1
self.count = 0
def is_full(self):
return self.count == self.MAX_QUEUE
def is_empty(self):
return self.count == 0
def size(self):
return self.count
def enqueue(self,item):
if not self.is_full():
self.back = (self.back+1)%self.MAX_QUEUE
self.items[self.back] = item
self.count +=1
else:
double_of_self_items = len(self.items)*2
new_list = [None]* double_of_self_items
MAX_QUEUE = double_of_self_items
back = MAX_QUEUE - 1
count = 0
back = (back + 1) % MAX_QUEUE
new_list[back] = self.items[back]
count += 1
print(new_list)
return new_list
def dequeue(self):
if not self.is_empty():
item = self.items[self.front]
self.front =(self.front+1)% self.MAX_QUEUE
self.count -=1
return item
else:
raise IndexError("The queue is empty.")
def peek(self):
if not self.is_empty():
item = self.items[self.front]
return item
else:
raise IndexError("The queue is empty.")
def __str__(self):
my_list = []
for i in self.items[self.front:]:
my_list.append(i)
for i in self.items[:self.back + 1]:
my_list.append(i)
return str(my_list)
q = CircularQueue(2)
q.enqueue(10)
q.dequeue()
q.enqueue(20)
q.enqueue(30)
q.enqueue(40)
print(q.size())
print(q.dequeue())
print(q.dequeue())
print(q.dequeue())
Excepted result:
3
20
30
40
Actual Result:
[30, None, None, None]
[20, None, None, None]
[30, None, None, None]
[20, None, None, None]
[30, None, None, None]
[20, None, None, None]
2
I'm not sure what you have the code you have, but in your enqueue method, simply check if you're full, increase the size if you are and then add the new item. That should simplify your logic and make your code more maintainable by having less flows.
def enqueue(self,item):
if is_full():
self.items = self.items + [None] * self.SOME_KIND_OF_INCREASE_DEFAULT
self.MAX_QUEUE = len(self.items)
self.back = (self.back+1)%self.MAX_QUEUE
self.items[self.back] = item
self.count +=1