Heap queue or heapq in Python (original) (raw)

A heap queue (also called a priority queue) is a data structure that allows quick access to the smallest (min-heap) or largest (max-heap) element.

**Example: Converting a normal list into a heap using heapify().

Python `

import heapq li = [25, 20, 15, 30, 40] heapq.heapify(li) print("Heap queue:", li)

`

Output

Heap queue: [15, 20, 25, 30, 40]

**Explanation: heapq.heapify(li) rearranges the list into a heap where the smallest element is at the root. It does not fully sort the list.

Why do we need Heap queue?

  1. Provides an efficient way to implement priority queues and maintain elements in heap order with minimal code and high performance.
  2. Useful in algorithms like Dijkstra's, Huffman encoding or any task requiring quick access to smallest element.
  3. Ideal for managing sorted data dynamically without full sorting after each operation.

Key Operations of a Heap

Heaps support several essential operations that help manage data efficiently while maintaining heap property.

Operation Function Description
Create heapq.heapify() Converts a regular list into a valid min-heap
Push heapq.heappush() Adds a new element to the heap while maintaining the heap property
Pop heapq.heappop() Removes and returns the smallest element from the heap
Peek heap[0] Accesses the smallest element without removing it
Push and Pop heapq.heappushpop() Pushes a new element and removes the smallest element in one step
Replace heapq.heapreplace() Removes the smallest element and inserts a new element in one operation

Using Heap as a Max-Heap

By default, Python's heapq implements a min-heap. To create a max-heap simply invert the values (store negative numbers).

**Example: Below example, convert a list into a max-heap by storing negative numbers and then retrieve the largest element:

Python `

import heapq
nums = [10, 20, 15, 30, 40]

Convert into a max-heap by inverting values

max_heap = [-n for n in nums]
heapq.heapify(max_heap)

Access largest element (invert sign again)

print("Largest element:", -max_heap[0])

`

Output

Largest element: 40

**Explanation: We store negative values so that the smallest (negative largest) is treated as root. When retrieving values, we multiply by -1 again to restore the original numbers.

Appending and Popping Elements

Elements can be inserted and removed while maintaining the heap property:

**Example: This code demonstrates how to create a heap, append an element and remove the smallest element.

Python `

import heapq h = [10, 20, 15, 30, 40] heapq.heapify(h)

Appending an element

heapq.heappush(h, 5) print(h)

Pop the smallest element from the heap

min = heapq.heappop(h) print("Smallest:", min) print(h)

`

Output

[5, 20, 10, 30, 40, 15] Smallest: 5 [10, 20, 15, 30, 40]

**Explanation:

Appending and Popping Simultaneously

heapq.heappushpop() pushes a new element onto the heap and removes the smallest element in a single operation.

**Example: Pushes 5 onto the heap and pops the smallest element in a single step using heappushpop().

Python `

import heapq h = [10, 20, 15, 30, 40] heapq.heapify(h) min = heapq.heappushpop(h, 5) print(min) print(h)

`

Output

5 [10, 20, 15, 30, 40]

**Explanation: heappushpop(h, 5) first pushes 5 into the heap and immediately pops the smallest element (which is also 5).

Finding Largest and Smallest Elements

heapq.nlargest() and heapq.nsmallest() return the required number of largest or smallest elements from an iterable.

**Example: Finding the 3 largest and 3 smallest elements using nlargest() and nsmallest()

Python `

import heapq h = [10, 20, 15, 30, 40] heapq.heapify(h)

maxi = heapq.nlargest(3, h) print("3 largest elements:", maxi)

min = heapq.nsmallest(3, h) print("3 smallest elements:", min)

`

Output

3 largest elements: [40, 30, 20] 3 smallest elements: [10, 15, 20]

**Note: The heapq module allows in-place heap operations on lists, making it an efficient and simple way to implement priority queues and similar structures.

Replace and Merge Operations

heapq.heapreplace() removes the smallest element and inserts a new one in a single step, returning the removed value. While, heapq.merge() combines multiple sorted iterables into a single sorted sequence.

**Example: This example replaces the smallest element in a heap and then merges it with another sorted list.

Python `

import heapq h1 = [10, 20, 15, 30, 40] heapq.heapify(h1)

min = heapq.heapreplace(h1, 5) print(min) print(h1)

h2 = [2, 4, 6, 8] h3 = list(heapq.merge(sorted(h1), sorted(h2))) print("Merged heap:", h3)

`

Output

10 [5, 20, 15, 30, 40] Merged heap: [2, 4, 5, 6, 8, 15, 20, 30, 40]

**Explanation:

Difference between heapreplace() and heappushpop()

  1. **heapreplace() always pops smallest element and then pushes a new one whereas, **heappushpop() pushes new element first, then pops smallest.
  2. Use **heapreplace() when you want the new element to be in the heap and **heappushpop() when new element may or may not stay (depending on comparison).

Advantages vs Disadvantages

Advantages Disadvantages
Fast for insertion and removal with priority. Not suitable for complex data manipulations
Uses less memory than some other data types. No direct access to middle items.
Simple to use with the heapq module. Can’t fully sort the items automatically.
Works in many cases like heaps and priority queues. Not safe with multiple threads at the same time.