Back to Data Structures & Algorithms
2026-03-146 min read

Types of Queue (Data Structures & Algorithms)

Learn Types of Queue (Data Structures & Algorithms) step by step with clear examples and exercises.

Why This Matters

Welcome to this full guide on understanding different types of queues in Python! This tutorial will delve into the core concepts, provide a worked example, discuss common mistakes, and offer practice questions to help you master the art of using queues effectively.

Queues are essential data structures used in various real-world scenarios like managing tasks in operating systems, simulating traffic lights, and handling requests in web servers. Understanding types of queues can help you solve complex problems efficiently and write more effective code. Additionally, familiarity with queues will be beneficial during job interviews and exams that test your understanding of data structures and algorithms.

Prerequisites

To fully grasp the concepts presented in this tutorial, you should have a good understanding of Python basics such as variables, functions, loops, and conditional statements. Familiarity with lists and dictionaries will also be helpful. It is recommended to review these topics before proceeding with this guide.

Core Concept

A queue is a linear data structure that follows a specific order (FIFO - First In, First Out). Elements are added to the rear of the queue, while elements are removed from the front. This makes queues particularly useful for situations where we need to maintain the order of processing items.

In Python, we can implement a queue using built-in collections.deque:

from collections import deque

queue = deque() # Empty queue
queue.append(1) # Add an element at the rear
queue.popleft() # Remove and return the front element (empty if queue is empty)

Types of Queues (expanded)

Although Python's built-in deque can handle most queue operations efficiently, it does not support priority queues out of the box. For situations requiring a priority queue, we can use the heapq module:

import heapq

priority_queue = [] # Empty priority queue
heapq.heappush(priority_queue, (3, 'apple')) # Add an element with priority 3 and label 'apple'
heapq.heappush(priority_queue, (1, 'banana')) # Add another element with priority 1 and label 'banana'
heapq.heappop(priority_queue) # Remove and return the highest priority element ('banana')

Priority Queues (expanded)

Priority queues are essential in situations where we need to process items based on their priorities, such as scheduling tasks or managing resources. Python's heapq module provides a simple way to implement a priority queue by using min-heaps for minimum-priority queues and max-heaps for maximum-priority queues.

import heapq

Minimum-priority queue (min-heap)

min_prio_queue = []

heapq.heappush(min_prio_queue, (1, 'apple')) # Add an element with priority 1 and label 'apple'

heapq.heappush(min_prio_queue, (2, 'banana')) # Add another element with priority 2 and label 'banana'

heapq.heappop(min_prio_queue) # Remove and return the lowest priority element ('apple')

Maximum-priority queue (max-heap)

max_prio_queue = []

heapq.heappush(max_prio_queue, (-1, 'apple')) # Add an element with priority -1 and label 'apple'

heapq.heappush(max_prio_queue, (-2, 'banana')) # Add another element with priority -2 and label 'banana'

heapq.heappop(max_prio_queue) # Remove and return the highest priority element ('banana')

Worked Example

Let's implement a simple server that handles incoming requests in the order they were received using a queue:

from collections import deque
import threading

requests = deque() # Request queue

def accept_request(label):
requests.append((threading.current_thread().name, label))

def process_request(req):
print(f'Processing request {req}')

def main():
for i in range(5):
t = threading.Thread(target=accept_request, args=('Request', i)) # Create a new thread to accept requests
t.start()

if len(requests) >= 3: # Process three requests at a time
for _ in range(3):
req = requests.popleft()
t = threading.Thread(target=process_request, args=(req,))
t.start()

if __name__ == '__main__':
main()

When you run this code, it creates five threads that simulate incoming requests. The main thread accepts requests and adds them to the queue. When there are at least three requests in the queue, it processes three requests concurrently by creating new threads for each request.

Common Mistakes

  1. Forgetting to import collections or heapq: Make sure you import deque from collections and heapq before using them in your code.
  2. Adding elements to the queue incorrectly: Remember that append() adds an element at the rear of the queue, while insert() can be used for adding elements at any position (not supported by built-in deque).
  3. Removing elements incorrectly: Ensure you use popleft() to remove and return the front element from a regular queue or heappop() to remove and return the highest priority element from a priority queue.
  4. Confusing priority queues with max/min heaps: Priority queues are implemented using heaps, but they differ in that elements have associated labels in addition to priorities.
  5. Incorrectly implementing custom priority queues: When implementing a custom priority queue, make sure you use the appropriate comparison function (< for min-heaps and > for max-heaps) when adding or removing elements from the heap.
  6. Ignoring edge cases in priority queue implementations: Be aware of potential edge cases such as empty queues, duplicate elements with the same priority, or situations where the priority queue is almost sorted (almost sorted means that only a few elements need to be swapped to achieve a fully sorted state).

Practice Questions

  1. Implement a FIFO queue that supports insertion and deletion at both ends (double-ended queue - deque).
  2. Write a function that finds the kth smallest element in an unsorted array using a min-priority queue.
  3. Implement a server that prioritizes processing requests based on their priority levels using a priority queue.
  4. Create a custom priority queue that supports both minimum and maximum priorities using a single heap (min-heap for minimum priorities and max-heap for maximum priorities).
  5. Write a program to simulate a bank teller system where customers arrive randomly, and the tellers process requests based on their priority levels (VIP customers have higher priority than regular customers).

FAQ

  1. What is the time complexity of append() and popleft() operations in Python's built-in deque? Both append() and popleft() have an average and worst-case time complexity of O(1).
  2. Can I create a custom priority queue with arbitrary priorities for elements? Yes, you can create a custom priority queue by using a dictionary to store the elements along with their priorities and then sorting the dictionary based on the priorities when needed. However, this approach may not be as efficient as using Python's built-in heapq module.
  3. What is the time complexity of heapq's heappush() and heappop() functions? Both heappush() and heappop() have an average and worst-case time complexity of O(log n).
  4. How can I implement a priority queue that supports both minimum and maximum priorities using a single heap? To implement a custom priority queue that supports both minimum and maximum priorities, you can use two separate lists (one for min-heap and one for max-heap) and maintain the invariant that the min-heap contains only negative priorities and the max-heap contains only positive priorities. When adding an element with a non-negative priority, you should add it to the max-heap; when adding an element with a negative priority, you should add it to the min-heap.
  5. What are some common use cases for priority queues? Priority queues are useful in various scenarios such as job scheduling, resource allocation, network routing, and game AI pathfinding. They can help optimize system performance by ensuring that high-priority tasks or events are processed before low-priority ones.
Types of Queue (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn