arrow-left

All pages
gitbookPowered by GitBook
1 of 4

Loading...

Loading...

Loading...

Loading...

Queue

Queues are a linear data structure that store data in a “first in, first out” (FIFO) order. Unlike arrays, you cannot access elements by index and instead can only pull the next oldest element. This m

Queue Sandboxchevron-rightQueue Continued...chevron-rightDequeuechevron-right
# lets think of another scenareo where we want to model a line at a store
#  or a queue at the airport

# for this comes the queue data structure

hashtag
Queue

  • Implement a Queue class from scratch with an existing bug, the bug is that it cannot take more than 5 elements.

  • Implement a Queue using two stacks. You may only use the standard push(), pop(), and peek() operations traditionally available to stacks. You do not need to implement the stack yourself (i.e. an array can be used to simulate a stack).

hashtag
Queues in Python

are a linear data structure that store data in a “first in, first out” (FIFO) order. Unlike arrays, you cannot access elements by index and instead can only pull the next oldest element. This makes it great for order-sensitive tasks like online order processing or voicemail storage.

You can think of a queue as a line at the grocery store; the cashier does not choose who to check out next but rather processes the person who has stood in line the longest.

We could use a Python list with append() and pop() methods to implement a queue. However, this is inefficient because lists must shift all elements by one index whenever you add a new element to the beginning.

Instead, it’s best practice to use the deque class from Python’s collections module. Deques are optimized for the append and pop operations. The deque implementation also allows you to create double-ended queues, which can access both sides of the queue through the popleft() and popright() methods.

Advantages:

  • Automatically orders data chronologically

  • Scales to meet size requirements

  • Time efficient with deque class

Disadvantages:

  • Can only access data on the ends

Applications:

  • Operations on a shared resource like a printer or

  • Serve as temporary storage for batch systems

  • Provides an easy default order for tasks of equal importance

hashtag
Common queue interview questions in Python

  • Reverse first k elements of a queue

  • Implement a queue using a linked list

  • Implement a stack using a queue

# lets think of another scenareo where we want to model a line at a store
#  or a queue at the airport

# for this comes the queue data structure
# like the stack we can add and remove data
# this is more like a line of people in a queue

# for this we could enqueue and item on to the data structure
# and we can dequeue an item from the queue

# This data structure works as a FIFO or (first in first out) data structure

# think of how you could utilise a linked list to create a queue

  
"""
A queue is a data structure whose primary purpose is to store and
return elements in First In First Out order. 
1. Implement the Queue class using an array as the underlying storage structure.
   Make sure the Queue tests pass.
2. Re-implement the Queue class, this time using the linked list implementation
   as the underlying storage structure.
   Make sure the Queue tests pass.
3. What is the difference between using an array vs. a linked list when 
   implementing a Queue?
   
Stretch: What if you could only use instances of your Stack class to implement the Queue?
         What would that look like? How many Stacks would you need? Try it!
"""

# Implement a Queue using an array for the underlying storage
# class QueueA:
#     def __init__(self):
#         self.storage = []

#     def __len__(self):
#         return len(self.storage)

#     def enqueue(self, value):
#         self.storage.append(value)


#     def dequeue(self):
#         if len(self.storage) == 0:
#             return None
#         return self.storage.pop(0)

class QueueA:
    def __init__(self):
        self.storage = [] 

    def __len__(self):
        return len(self.storage)

    def enqueue(self, value):
        self.storage.append(value)

    def dequeue(self):
        if len(self.storage) == 0:
            return None
        return self.storage.pop(0)


from linked_list import LinkedList

# Queue implementation using a Linked List for the underlying storage
class QueueL:
    def __init__(self):
        self.storage = LinkedList()
        self.size = 0

    def __len__(self):
        return self.size

    def enqueue(self, item):
        self.storage.add_to_tail(item)
        self.size += 1

    def dequeue(self):
        if self.size == 0:
            return None
        self.size -= 1
        return self.storage.remove_head()

class QueueLL(LinkedList):
    def __init__(self):
        super().__init__()
        self.size = 0

    def enqueue(self, item):
        self.add_to_tail(item)
        self.size += 1

    def dequeue(self):
        if self.size == 0:
            return None
        self.size -= 1
        return self.remove_head()
    
# FIFO: first in first out

# create the abstract data type
class Queue:
    def __init__(self):
        # initialize it to a one dimensional array or linked list
        self.queue = []

    """
    Stack methods (enqueue, dequeue, peek, is_empty, size_queue)
    """

    # function to check if the queue is empty O(1)
    def is_empty(self):
        return self.queue == []

    # function to add data to the queue O(1)
    def enqueue(self, data):
        self.queue.append(data)

    # function to remove and return the first item inserted to the queue O(N)
    def dequeue(self):

        # first check to make sure its not an empty queue
        if self.size_queue()!= 0:
            # get the first item in the queue
            data = self.queue[0]
            # remove it
            del self.queue[0]
            # return the item
            return data
        else:
            return -1

    # function to return the first item in the queue without removing it
    # O(1)
    def peek(self):
        return self.queue[0]

    # function get the size of the queue O(1)
    def size_queue(self):
        return len(self.queue)


"""
Using the methods
"""
queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
print(f'Size: {queue.size_queue()}')
print(f'Dequeue: {queue.dequeue()}')
print(f'Size: {queue.size_queue()}')
print(f'Peeked item: {queue.peek()}')
print(f'Size: {queue.size_queue()}')
# like the stack we can add and remove data
# this is more like a line of people in a queue
# for this we could enqueue and item on to the data structure
# and we can dequeue an item from the queue
# This data structure works as a FIFO or (first in first out) data structure
# think of how you could utilise a linked list to create a queue
"""
A queue is a data structure whose primary purpose is to store and
return elements in First In First Out order.
1. Implement the Queue class using an array as the underlying storage structure.
Make sure the Queue tests pass.
2. Re-implement the Queue class, this time using the linked list implementation
as the underlying storage structure.
Make sure the Queue tests pass.
3. What is the difference between using an array vs. a linked list when
implementing a Queue?
Stretch: What if you could only use instances of your Stack class to implement the Queue?
What would that look like? How many Stacks would you need? Try it!
"""
# Implement a Queue using an array for the underlying storage
class QueueA:
def __init__(self):
self.storage = []
def __len__(self):
return len(self.storage)
def enqueue(self, value):
self.storage.append(value)
def dequeue(self):
if len(self.storage) == 0:
return None
return self.storage.pop(0)
from linked_list import LinkedList
# Queue implementation using a Linked List for the underlying storage
class QueueL:
def __init__(self):
self.storage = LinkedList()
self.size = 0
def __len__(self):
return self.size
def enqueue(self, item):
self.storage.add_to_tail(item)
self.size += 1
def dequeue(self):
if self.size == 0:
return None
self.size -= 1
return self.storage.remove_head()
Queuesarrow-up-right
CPU corearrow-up-right
Arraychevron-right
Binary Search Treechevron-right
Linked Listchevron-right
Extra-Arraychevron-right
Stackchevron-right
Binary Treechevron-right
Recursionchevron-right
Hash Tablechevron-right
Searchingchevron-right
Sortingchevron-right
Queue Sandboxchevron-right
Hash Tablechevron-right
Double Linked Listchevron-right
Graphschevron-right
Exoticchevron-right
Heapchevron-right
"""Make a Queue class using a list!
Hint: You can use any Python list method
you'd like! Try to write each one in as
few lines as possible.
Make sure you pass the test cases too!"""

class Queue:
    def __init__(self, head=None):
        self.storage = [head]

    def enqueue(self, new_element):
        if(self.storage):
            self.storage.append(new_element)
        else:
            self.storage = [new_element]
        return new_element

    def peek(self):
        if(self.storage):
            return self.storage[0]
        else:
            return None

    def dequeue(self):
        if(self.storage):
            return self.storage.pop(0)
        else:
            return None

# Setup
q = Queue(1)
q.enqueue(2)
q.enqueue(3)

# Test peek
# Should be 1
print q.peek()

# Test dequeue
# Should be 1
print q.dequeue()

# Test enqueue
q.enqueue(4)
# Should be 2
print q.dequeue()
# Should be 3
print q.dequeue()
# Should be 4
print q.dequeue()
q.enqueue(5)
# Should be 5
print q.peek()
"""Make a Queue class using a list!
Hint: You can use any Python list method
you'd like! Try to write each one in as
few lines as possible.
Make sure you pass the test cases too!"""

class Queue:
    def __init__(self, head=None):
        self.storage = [head]

    def enqueue(self, new_element):
        if(self.storage):
            self.storage.append(new_element)
        else:
            self.storage = [new_element]
        return new_element

    def peek(self):
        if(self.storage):
            return self.storage[0]
        else:
            return None

    def dequeue(self):
        if(self.storage):
            return self.storage.pop(0)
        else:
            return None

# Setup
q = Queue(1)
q.enqueue(2)
q.enqueue(3)

# Test peek
# Should be 1
print q.peek()

# Test dequeue
# Should be 1
print q.dequeue()

# Test enqueue
q.enqueue(4)
# Should be 2
print q.dequeue()
# Should be 3
print q.dequeue()
# Should be 4
print q.dequeue()
q.enqueue(5)
# Should be 5
print q.peek()

Dequeue

"""
A deque is similar to all of the other sequential data structures but
has some implementation details that are different from other sequences
like a list. This module highlights those differences and shows how
a deque can be used as a LIFO stack and a FIFO queue.
"""
from collections import deque


def main():
    # A list is identical to a vector where a new array is created when
    # there are too many elements in the old array, and the old array
    # elements are moved over to the new array one-by-one. The time
    # involved with growing its size increases linearly. A deque is
    # identical to a doubly linked list whose nodes have a left pointer
    # and a right pointer. In order to grow the linked list, a new node
    # is created and added to the left, or the right, of the linked list.
    # The time complexity involved with growing its size is constant.
    # Check out the source code for a list and a deque here:
    # https://github.com/python/cpython/blob/3.8/Objects/listobject.c
    # https://github.com/python/cpython/blob/3.8/Modules/_collectionsmodule.c
    dq = deque()

    for i in range(1, 5):
        # Similar to adding a new node to the right of the linked list
        dq.append(i)

        # Similar to adding a new node to the left of the linked list
        dq.appendleft(i * 2)

    # A deque can be iterated over to build any data structure
    assert [el for el in dq] == [8, 6, 4, 2, 1, 2, 3, 4]
    assert tuple(el for el in dq) == (8, 6, 4, 2, 1, 2, 3, 4)
    assert {el for el in dq} == {8, 6, 4, 2, 1, 3}

    # A deque can be used as a stack
    # https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
    assert dq.pop() == 4
    assert dq.pop() == 3

    # A deque can be used as a queue
    # https://en.wikipedia.org/wiki/Queue_(abstract_data_type)
    assert dq.popleft() == 8
    assert dq.popleft() == 6


if __name__ == "__main__":
    main()

Queue Sandbox

# -*- coding: utf-8 -*-
"""qandstack.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1Nr_QNCQNn2BqTil9swxDWfpsBcdumEbQ

# Queues and Stacks

## Queue
- think of a queue as a line of people queing up to be served
- FIFO (First In First Out)

## Stack
- think of a stack as a stack of recipts on a nail or pin
- LIFO (Last In First Out)

What data structure could be of use as an underlying data storage for a stack or queue?
"""

# lets write a simple stack
class Stack:
    def __init__(self):
        self.storage = []

    def push(self, item):
        """
    push the item on to the top of the stack
    """
        self.storage.append(item)

    def pop(self):
        """
    pop the item from the top of the stack returning said item if there is anything on the stack.
    otherwise return "The Stack is Empty"
    """
        if len(self.storage) > 0:
            return self.storage.pop()
        return "The Stack is Empty"

    def peek(self):
        if len(self.storage) > 0:
            return self.storage[-1]
        return "The Stack is Empty"


s = Stack()
s.push(10)
s.push(20)
s.push(30)
l = []
l.append(s.pop())
l.append(s.pop())
l.append(s.pop())
print(l)

# lets write a simple queue
class Queue:
    def __init__(self):
        self.storage = []

    def enqueue(self, item):
        """
    enqueues the item in to the queue
    """
        self.storage.append(item)

    def dequeue(self):
        """
    dequeue the item from the front of the queue returning said item if there is anything on the queue.
    otherwise return "The Queue is Empty"
    """
        if len(self.storage) > 0:
            return self.storage.pop(0)
        return "The Queue is Empty"


q = Queue()
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)

l2 = []
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())

print(l2)

# lets write a more performant queue
"""
  F      R
[10]-> [20]-> None
"""


class LLNode:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"[{self.data}]"


class LLQueue:
    def __init__(self):
        self.front = None
        self.rear = None

    def enqueue(self, item):
        new_node = LLNode(item)

        if self.rear is None:
            self.front = new_node
            self.rear = new_node
        else:
            self.rear.next = new_node
            self.rear = new_node

    def dequeue(self):
        old_front = "The Queue is Empty"
        if self.front is not None:
            old_front = self.front
            self.front = old_front.next

        if self.front is None:
            self.rear = None

        return old_front


q = LLQueue()
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)

l2 = []
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())
l2.append(q.dequeue())

print(l2)

"""# Break
# CODE 8119
"""

# lets write a more performant stack
class LLNode:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"[{self.data}]"


class LLStack:
    def __init__(self):
        self.top = None

    def push(self, data):
        new_node = LLNode(data)
        new_node.next = self.top
        self.top = new_node

    def pop(self):
        if self.top is not None:
            poped_node = self.top
            self.top = poped_node.next

            return poped_node
        else:
            return "The Stack is Empty"


"""# Demos"""

"""
You've encountered a situation where you want to easily be able to pull the
largest integer from a stack.
You already have a `Stack` class that you've implemented using a dynamic array.
Use this `Stack` class to implement a new class `MaxStack` with a method
`get_max()` that returns the largest element in the stack. `get_max()` should
not remove the item.
*Note: Your stacks will contain only integers. You should be able to get a
runtime of O(1) for push(), pop(), and get_max().*
"""


class Stack:
    def __init__(self):
        """Initialize an empty stack"""
        self.items = []

    def push(self, item):
        """Push a new item onto the stack"""
        self.items.append(item)

    def pop(self):
        """Remove and return the last item"""
        # If the stack is empty, return None
        # (it would also be reasonable to throw an exception)
        if not self.items:
            return None

        return self.items.pop()

    def peek(self):
        """Return the last item without removing it"""
        if not self.items:
            return None
        return self.items[-1]


class MaxStack:
    def __init__(self):
        # Your code here
        self.stack = Stack()
        self.maxes_stack = Stack()

    def push(self, item):
        """Add a new item onto the top of our stack."""
        # Your code here
        self.stack.push(item)

        if self.maxes_stack.peek() is None or item >= self.maxes_stack.peek():
            self.maxes_stack.push(item)

    def pop(self):
        """Remove and return the top item from our stack."""
        # Your code here
        item = self.stack.pop()

        if item == self.maxes_stack.peek():
            self.maxes_stack.pop()

        return item

    def get_max(self):
        """The last item in maxes_stack is the max item in our stack."""
        # Your code here
        return self.maxes_stack.peek()


ms = MaxStack()
ms.push(20)
ms.push(30)
ms.push(9)
ms.push(102)
ms.push(33)
ms.push(1)
ms.pop()
ms.pop()
ms.pop()
print(ms.get_max())

"""# Optionals"""

"""
Your goal is to define a `Queue` class that uses two stacks. Your `Queue` class
should have an `enqueue()` method and a `dequeue()` method that ensures a
"first in first out" (FIFO) order.
As you write your methods, you should optimize for time on the `enqueue()` and
`dequeue()` method calls.
The Stack class that you will use has been provided to you.
"""


class Song:
    def __init__(self, name, link):
        self.name = name
        self.link = link

    def __repr__(self):
        return f"{self.name}: {self.link}"


s1 = Song("Bob The Builder", "http://www.gogle.co.uk/")
s2 = Song("Eclipse - Pink Floyd 1", "http://www.yashoo.com")
s3 = Song("Bob The Builder 2", "http://www.gogle.co.uk/")
s4 = Song("Eclipse - Pink Floyd 2", "http://www.yashoo.com")
s5 = Song("Bob The Builder 3", "http://www.gogle.co.uk/")
s6 = Song("Eclipse - Pink Floyd 3", "http://www.yashoo.com")
s7 = Song("Bob The Builder", "http://www.gogle.co.uk/")
s8 = Song("Eclipse - Pink Floyd Uncut", "http://www.yashoo.com")


class Stack:
    def __init__(self):
        self.data = []

    def push(self, item):
        self.data.append(item)

    def pop(self):
        if len(self.data) > 0:
            return self.data.pop()
        return "The stack is empty"


class QueueTwoStacks:
    def __init__(self):
        # Your code here
        self.in_stack = Stack()
        self.out_stack = Stack()

    def enqueue(self, item):
        # Your code here
        self.in_stack.push(item)

    def dequeue(self):
        # Your code here
        if len(self.out_stack.data) == 0:
            while len(self.in_stack.data) > 0:
                stack_item = self.in_stack.pop()
                self.out_stack.push(stack_item)
            if len(self.out_stack.data) == 0:
                return "can not dequeue from an empty queue"

        return self.out_stack.pop()


# q = QueueTwoStacks()
# q.enqueue(20)
# q.enqueue(220)
# q.enqueue(201)
# q.enqueue(120)
# q.enqueue(230)
# q.enqueue(320)
# q.enqueue(3)

# l3 = []
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())
# l3.append(q.dequeue())

q = QueueTwoStacks()
q.enqueue(s1)
q.enqueue(s2)
q.enqueue(s3)
q.enqueue(s4)
q.enqueue(s5)
q.enqueue(s6)
q.enqueue(s7)

l3 = []
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())
l3.append(q.dequeue())

print(l3)

Queue Continued...

hashtag
Queue

Similar to a stack, the queue also limits the position for inserting and removing am operation on a sequence of data. However, unlike a stack, a queue follows the first in, first out (FIFO) principle.

In Python, a queue can also be implemented using a list. To follow the FIFO principle, the inserting operation occurs at the tail of the list, while the removing operation occurs at the head of the list.Python implementation of a queue

hashtag
Table of Contents

hashtag
Queue - An introduction

A Queue is a linear data structure in which data is stored in a First In, First Out manner. In a queue, the item that was added the earliest is removed first. The item that was added more recently is removed last. A queue can be compared to a real-life queue.

enqueue is a queue operation where you add an item at the back of a queue.

dequeue is a queue operation where you remove an item from the front of a queue.

hashtag
Uses of Queues

  • Operating Systems - often maintain queues while implementing various low-level operations such as CPU Scheduling, Disk Scheduling, etc.

  • Hardware - hardware interrupts are handled using queues.

  • Internet - Website traffic handling.

hashtag
Implementing Queues

Queue Methods

queue.Enqueue()

  • The queue.Enqueue() method adds an element at the rear of the queue.

  • Time Complexity -> O(1)

queue.Dequeue()

  • The queue.Dequeue() method removes an element from the front of the queue.

  • Time Complexity -> O(1)

queue.Front()

  • The queue.Front() method returns the front item from the queue.

  • Time Complexity -> O(1)

queue.Rear()

  • The queue.Rear() method returns the rear item from the queue.

  • Time Complexity -> O(1)

queue.isEmpty()

  • The queue.isEmpty() method returns True if the queue is empty, else returns False.

  • Time Complexity -> O(1)

Queues can be implemented in various ways. Let us look at how to implement a queue using a list and using the collections.deque module in Python.

Queue using a List

We can use the list methods insert and pop to implement a queue.

Queue using collections.Deque

The deque class from the python collections module can also be used to implement a queue. This method of implementing a queue is far more efficient because deque provides faster enqueue and dequeue operations.

hashtag
Practice Queues

Try implementing the queue in Python first. Then once you’re done with the implementation, try solving these problems on and

  • Reversing a Queue -

  • Sort the Queue using Recursion -

  • Reversing First K Elements of the Queue -

  • And all other scenarios where a First In, First Out priority has to be implemented.

    Implementing Stack using Queues -

  • Queries with Fixed Length -

  • Truck Tour -

  • Maximum Sum of Triangle No Less Than K -

  • Design Circular Queue -

  • Design Circular Dequeue -

  • Queue: Introductionarrow-up-right
    Uses of Queuesarrow-up-right
    Implementing Queuesarrow-up-right
    HackerRankarrow-up-right
    LeetCodearrow-up-right
    GeeksforGeeksarrow-up-right
    GeeksforGeeksarrow-up-right
    GeeksforGeeksarrow-up-right
    Queue, Diagram
    class Queue:
    
        def __init__(self):
            """
            Initializing Queue.
            """
            self.queue = []
    
        def isEmpty(self) -> bool:
            return True if len(self.queue) == 0 else False
    
        def front(self) -> int:
            return self.queue[-1]
    
        def rear(self) -> int:
            return self.queue[0]
    
        def enqueue(self, x: int) -> None:
            self.x = x
            self.queue.insert(0, x)       
    
        def dequeue(self) -> None:
            self.queue.pop()
    from collections import deque
    class Queue:
    
        def __init__(self):
            """
            Initializing Queue.
            """
            self.queue = deque()
    
        def isEmpty(self) -> bool:
            return True if len(self.queue) == 0 else False
    
        def front(self) -> int:
            return self.queue[-1]
    
        def rear(self) -> int:
            return self.queue[0]
    
        def enqueue(self, x: int) -> None:
            self.x = x
            self.queue.append(x)       
    
        def dequeue(self) -> None:
            self.queue.popleft()
    Practice Queuesarrow-up-right
    Conclusionarrow-up-right
    GeeksforGeeksarrow-up-right
    HackerRankarrow-up-right
    HackerRankarrow-up-right
    LeetCodearrow-up-right
    LeetCodearrow-up-right
    LeetCodearrow-up-right