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

Priority Queue Data Structure (Data Structures & Algorithms)

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

Why This Matters

In the realm of data structures and algorithms, understanding how to implement and use a Priority Queue is crucial for solving real-world problems that require efficient handling of tasks or events with varying priorities. A Priority Queue can significantly improve the performance of your code in various scenarios, such as scheduling tasks, managing resources, or simulating complex systems.

In this lesson, we will delve into the practical aspects of implementing a Priority Queue using Python, focusing on its applications, key concepts, common mistakes, and practice questions to help you master this essential data structure.

Prerequisites

To fully grasp the material in this lesson, you should have a solid understanding of the following:

  1. Basic Python syntax and control structures (loops, conditionals)
  2. Data structures like lists and dictionaries
  3. Functions and methods in Python
  4. Understanding of Big O notation for time complexity analysis
  5. Familiarity with heap-based data structures is helpful but not required

Core Concept

A Priority Queue is a specialized data structure that maintains a collection of elements, each with an associated priority value. The elements are ordered according to their priorities, with the highest-priority element always at the front of the queue. Priority Queues can be implemented using various methods, such as heaps or binary search trees, but we will focus on the common and efficient heap-based implementation in Python.

Heap-Based Priority Queue Implementation

A heap-based Priority Queue is an array that adheres to either a min-heap or max-heap property. In a min-heap, the root node (index 0) has the smallest value, while in a max-heap, the root node has the largest value. For simplicity, we will focus on implementing a max-heap Priority Queue in this lesson.

To create a heap-based Priority Queue in Python, we can use a list and implement several key operations:

  1. insert(item): Add an item to the Priority Queue with its associated priority value.
  2. delete_max(): Remove and return the highest-priority item from the Priority Queue.
  3. get_max(): Return the highest-priority item in the Priority Queue without removing it.
  4. is_empty(): Check if the Priority Queue is empty.
  5. size(): Get the current size of the Priority Queue.
  6. rebuild_heap(index): Rebuild the heap property starting from a given index.

Here's an example implementation of a max-heap Priority Queue in Python:

class PriorityQueue:
def __init__(self):
self.queue = []

def insert(self, item, priority):
self.queue.append((priority, item))
self._swim(len(self.queue) - 1)

def delete_max(self):
if not self.queue:
return None
max_item = self.queue[0][1]
last_item = self.queue.pop()
if self.queue:
self.queue[0] = last_item
self._sink(0)
return max_item

def get_max(self):
if not self.queue:
return None
return self.queue[0][1]

def is_empty(self):
return len(self.queue) == 0

def size(self):
return len(self.queue)

def _swim(self, k):
while k > 1 and self._greater(k // 2, k):
self._swap(k // 2, k)
k = k // 2

def _sink(self, k):
left_child = 2 * k + 1
right_child = 2 * k + 2
max_index = k
if left_child < len(self.queue) and self._greater(left_child, max_index):
max_index = left_child
if right_child < len(self.queue) and self._greater(right_child, max_index):
max_index = right_child
if max_index != k:
self._swap(max_index, k)
self._sink(max_index)

def _greater(self, i, j):
return self.queue[i][0] > self.queue[j][0]

def _swap(self, i, j):
self.queue[i], self.queue[j] = self.queue[j], self.queue[i]

Worked Example

Let's consider a practical example of using a Priority Queue to solve a real-world problem: scheduling tasks with varying deadlines and priorities. Suppose we have a set of tasks with their respective deadlines and priorities, as shown below:

| Task ID | Deadline | Priority |

|----------|-----------|-----------|

| T1 | 5 | 3 |

| T2 | 7 | 1 |

| T3 | 6 | 2 |

| T4 | 8 | 4 |

To schedule these tasks efficiently, we can create a Priority Queue and insert the tasks accordingly:

pq = PriorityQueue()
for task_id, deadline, priority in [('T1', 5, 3), ('T2', 7, 1), ('T3', 6, 2), ('T4', 8, 4)]:
pq.insert(task_id, priority)

Now we can schedule the tasks by repeatedly removing and executing the highest-priority task until the Priority Queue is empty or all deadlines have passed:

while not pq.is_empty():
task = pq.delete_max()
if datetime.datetime.now().day >= int(task[0]): # Replace with actual date handling code
print("Executing task:", task[1])
else:
print("Task", task[1], "has not yet come due.")

Common Mistakes

  1. Forgetting to update the heap property after inserting or deleting an item (swim and sink operations).
  2. Implementing a min-heap instead of a max-heap, leading to incorrect results when dealing with priorities.
  3. Using an inefficient implementation for the underlying data structure (e.g., using lists instead of arrays for better memory access).
  4. Failing to handle edge cases, such as an empty Priority Queue or tasks with identical deadlines and priorities.
  5. Misunderstanding Big O notation and not considering the time complexity of operations when comparing different Priority Queue implementations.

Practice Questions

  1. Implement a min-heap Priority Queue in Python using the heapq module.
  2. Modify the max-heap Priority Queue implementation to handle tasks with identical deadlines and priorities.
  3. Analyze the time complexity of each operation in the max-heap Priority Queue implementation.
  4. Use a Priority Queue to solve the Huffman coding problem.
  5. Implement a custom binary search tree-based Priority Queue in Python.

FAQ

What is the difference between a min-heap and a max-heap?

A min-heap has the smallest value at the root, while a max-heap has the largest value at the root. In a min-heap, the smallest element is always removed first, whereas in a max-heap, the highest-priority element is always removed first.

Why do we use heap-based data structures for Priority Queues?

Heap-based Priority Queues offer efficient insertion and deletion of elements, with operations like insert and delete_max having a time complexity of O(log n). This makes them suitable for handling large datasets with varying priorities.

Can we implement a Priority Queue using other data structures like linked lists or arrays?

Yes, it is possible to implement a Priority Queue using other data structures, but heap-based implementations are generally more efficient due to their logarithmic time complexity for common operations.

How can we handle tasks with identical deadlines and priorities in the max-heap Priority Queue implementation?

To handle tasks with identical deadlines and priorities, we can maintain a separate count of such tasks and insert them multiple times accordingly. Alternatively, we can use a custom data structure like a binary search tree to store the tasks and enforce the ordering based on both deadline and priority.

What is the time complexity of the _swim() and _sink() functions in the max-heap Priority Queue implementation?

The _swim() function has a time complexity of O(log n) in the worst case, while the _sink() function also has a time complexity of O(log n) in the worst case. These functions are essential for maintaining the heap property after inserting or deleting an element.

Priority Queue Data Structure (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn