What is a Queue in Data Structures? Key Concepts Explained

What is a Queue in Data Structures? Key Concepts Explained

Welcome to Queue blog!

What is Queue?

Queue is similar as real life queue. In python, queue is a data structure that store items in a first in/first out system. In queue, we follow the FIFO method.

Queue example : Receiving orders, Printer queue, Call center application etc.

Queue using Python List - no size limit

We can implement ques in two ways - Python List, Linked List.

  1. Python List

    - Queue without capacity

    - Queue with capacity (Circular queue)

  2. Linked List

In case of creating a queue:

Using python list (without capacity), we initialize an empty python list. Then we insert elements into the list. In queue, insertion is known as Enqueue.

In case of removing :

Removing is known as dequeue. If we call dequeue method, it will return the first element of the queue, the element will be removed from the queue also. (you can not run dequeue operation on empty list)

Peek operation :

This method will always return the first element no matter how many time you run it. It will give different result only if you modify the queue list.

isEmpty : Checks if the queue is empty of not.

isFull : Checks if the queue is up to its maximum capacity.

Queue using Python List - no size limit , operations (enqueue, dequeue, peek)

class Queue: 
    def __init__(self): 
        self.items = []
    def __str__(self):
        values = [str(x) for x in self.items] 
        return ' '.join(values)

    def isEmpty(self): 
        if self.items == []: 
            return True 
        return False 

    def enqueue(self, value):  #On^c time complexity
        self.items.append(value) 
        return "Element inserted at the end of the queue"

    def dequeue(self):
        if self.isEmpty(): 
            return "No element" 
        return self.items.pop(0) #index of 1st element

    def peek(self): 
        if self.isEmpty(): 
            return "No element in the queue" 
        return self.items(0)

    def delete(self): 
        self.items = None 

customQueue = Queue()
print(customQueue.isEmpty())
customQueue.enqueue(2) 
print(customQueue)

Circular Queue - Python List, operations (enqueue, dequeue, peek, delete)

A circular queue is a data structure that uses a singles, fixed size buffer as if it is connected end-to-end. This is efficient when you want to uses a fixed size memory.

Explanation:

start and top refers to specific position/pointers. Generally, start means the beginning of a data structure. In queue, it is the position from where elements are dequeued (deques from the start). On the other hand, top represents the position where an element has been recently add.

class Queue: 
    def __init__(self, maxSize): 
        self.items = maxSize = [None]
        self.maxSize = maxSize
        self.start = -1 
        self.top =  -1
    def __str__(self): 
        values = [str(x) for x in self.items] 
        return ' '.join(values)

    def isFull(self):
        if self.top + 1 == self.start: 
            return True 
        elif self.start == 0 and self.top + 1 == self.maxSize:
            return True 
        else: 
            return False 

    def isEmpty(self): 
        if self.top == -1: 
            return True 
        else: 
            return False

    def enqueue(self,value): 
        if self.isFull():
            return "Queue is full" 
        else: 
            if self.top + 1 == self.maxSize: 
                self.top = 0
            else: 
                self.top += 1
                if self.start == -1: 
                    self.start = 0
            self.items[self.top] = value
            return "The element is inserted at the end of the queue"

    def dequeue(self): 
        if self.isEmpty(): 
            return "There is not any element in the queue" 
        else: 
            firstElement = self.items[self.start]
            start = self.start 
            if self.start == self.top: 
                self.start = -1 
                self.top = -1
            elif self.start + 1 == self.maxSize: 
                self.start = 0
            else: 
                self.start += 1 
            self.items[start] = None 
            return firstElement

    def peek(self): 
        if self.isEmpty(): 
            return "There is not any element in the queue" 
        else: 
            return self.items[self.start]

    def delete(self): 
        self.items = self.maxSize = [None] 
        self.top = -1 
        self.start = -1

customQueue = Queue(3)
print(customQueue.isFull())
customQueue.enqueue(3)
print(customQueue)
print(customQueue.isFull())
print(customQueue.dequeue())
print(customQueue)
print(customQueue.peek())
print(customQueue.delete())
print(customQueue)

For init method - We are just updating, initializing the variables. Hence, the time complexity is O(N). If the max size is N, The space complexity will be O(N). Everything else has O(1) time and space complexity.

Queue - Linked List, Operations (Create, Enqueue)

Code:

class Node: 
    def __init__(self, value = None): 
        self.value = value 
        self.next = None 
    def __str(self): 
        return str(self.value)

class LinkedList: 
    def __init__(self): 
        self.head = None 
        self.tail = None 
    def __iter__ (self): 
        curNode = self.head 
        while curNode: 
            yield curNode:
            curNode = curNode.next 
class Queue : 
    def __init__(self): 
        self.linkedList = LinkedList()
    def __str__(self): 
        values = [str(x) for x in self.linkedList] 
        return ' '.join(values)

    def enqueue(self, value): 
        newNode = Node(value) 
        if self.linkedList == None: 
            self.linkedList.head = newNode 
            self.linkedList.tail = newNode 
        else: 
            self.linkedList.tail.next = newNode 
            self.linkedList.tail = newNode

custQueue = Queue() 
custQueue.enqueue(1)
custQueue.enqueue(2)
custQueue.enqueue(3)
print(custQueue)

Explanation:

First, we will create a Node class. Then, we will add the __str__ function (a standard function in Python) to make the nodes printable. With this, our node class is finished.

Next, the linked list class. After setting head and tail, we will make the list inerrable because without iterating, we cannot printout the queue. In the __iter__ function, we are just iterating through the linked list yielding the values of nodes in one list.

Now, we will create our queue class. Inside __init__ function of this queue class, we need to initialize an object of the LinkedList over here (the object of LinkedList).

Queue - Linked List, Operations (Dequeue(), isEmpty, Peek)

We are going to add some other methods here also. It's the extension of the previous linked link class.

Code:

    def isEmpty(self): 
        if self.linkedList.head == None: 
            return True 
        else: 
            return False. 

    def dequeue(self): 
        if self.isEmpty(): 
            return "No elements" 
        else: 
            tempNode = self.linkedList.head
            if self.linkedList.head == self.linkedList.tail: 
                self.linkedList.head = None 
                self.linkedList.tail = None 
            else: 
                self.linkedList.head = self.linkedList.head.next 
            return tempNode

    def peek(self):
        if self.isEmpty(): 
            return "No elements in the list" 
        else: 
            return self.linkedList.head

    def delete(self): 
        self.linkedList.head = None 
        self.linkedList.tail = None 

print(custQueue.dequeue())
print(custQueue)
print(custQueue.peek())
print(custQueue)

Explanation:

We will use the isEmpty() method in the dequeue method, so I initialized it first. To check if there's any element in the list, we check the head reference. If the head reference is none, there are no elements in the linked list.

Now let's continue to dequeue method. When we dequeue an element, we need to return the first element and remove it from the queue. If there are elements in the queue, we will proceed by making a temp Node which will take the value of the head and will return the value. Then we will do the rest following the if-else condition.

Now we will develop the peek method. Peek method is used for returning the first element from the queue. We are not updating, modifying anything. We are simply returning the first element.

To delete, we just need to update the head, tail reference to None.

Everything here has O(1) time and space complexity.

End.