How to easily Implement Priority Queue in Python
By: Aditya Dhanraj Tiwari
Tags: Python Programming, Heapq, Priority Queue, Data Structures, Algorithms

How to easily Implement Priority Queue in Python

Take advantage of the heapq module to implement a Priority Queue

dbader.org

What is a Priority Queue?

A Priority Queue is a type of queue in which every element is associated with priority and it returns the element of highest priority on every pop operation.

if priority is same the elements are return on basis of their insertion order.

We can easily implement priority queue in Python using heapq module.

import heapq class PriorityQueue: def __init__(self):

self._data = []

self._index = 0 def push(self, item, priority):

heapq.heappush(self._data, (-priority, self._index, item))

self._index += 1 def pop(self):

return heapq.heappop(self._data)[-1]

The above code implement priority queue. Let’s see example of how to use it.

class Task: def __init__(self,name):

self.name = name



def __str__(self):

return f'{self.name}' queue = PriorityQueue() # Create Priority queue # Insert task in queue using push() method

queue.push(Task('daemon'), 23)

queue.push(Task('app'), 12)

queue.push(Task('os'),40)

queue.push(Task('service'),23) # use pop() method to fetch element of highest priority

print(queue.pop()) # os

print(queue.pop()) # daemon

print(queue.pop()) # service

print(queue.pop()) # app

You can see pop operation on queue always return Task with highest priority and if priority is same it return Task on basis of their insertion order (daemon and service).

Let’s understand the code

The main idea here is to take advantage of heapq module. First we have imported heapq module.

import heapq

Next we have created PriorityQueue class which have 2 fields _data and _index.

_data is a list which stores the elements and _index is used to keep track of insertion order, use of _index will be explained further.

class PriorityQueue: def __init__(self):

self._data = []

self._index = 0

We will use heapq.heappush() and heapq.heappop() function from heapq module to implement push and pop method in PriorityQueue respectively.

heapq.heappush() → it always insert the item in such a way that the first element of queue has lowest priority.

heapq.heappush(self._data, (-priority, self._index, item))

It takes two argument, queue itself and item to be inserted. In our case we are inserting item in form of tuple (-priority, self._index, item)

priority is negated so that first element of queue always has highest priority. This is opposite of normal ordering of heap which stores the data from smallest to highest priority.

Let’s take example to understand how tuples are compared and importance of self._index.

a = (23, Task('os'))

b = (45, Task('deamon')) print(a > b) # False

When you compare two tuples in Python, first item from both tuple are compared. Here 23 and 45 are compared and because 23 is not greater than 45 the result of a > b is False.

What if first item of both tuple is same? In that case, next elements are compared until result of comparison is determined.

a = (45, Task('os'))

b = (45, Task('deamon'))

print(a > b)

Running above code, will give you error.

Traceback (most recent call last):

File "main.py", line 10, in <module>

print(a > b)

TypeError: unorderable types: Task() > Task()

As value of first element of both tuple a and b is same, next element Task() are compared. Comparing Task gives error as Task() can not be ordered.

To work with Task, with same priority level, we are inserting self._index which gives us two benefits →

It let comparison operator work for Task with same priority. Task will never be compared as index of two task will not be same. We are using constantly increasing index self._index += 1 which help in sorting the item on basis of insertion order.

a = (45, 0, Task('os'))

b = (45, 1, Task('deamon')) print(a > b) # False

You can find more example and discussion on comparison and implementation of heap here.

Now last part of code, pop method.

def pop(self):

return heapq.heappop(self._data)[-1]

heapq.heappop() takes one argument queue itself and return the first element of queue. we are using [-1] to return only Task from tuple.

In our implementation, push() and pop() operation has O(logN) complexity where N is number of item in PriorityQueue, they are very efficient even for large value of N.

I hope you have enjoyed this article. Good Luck and Happy Coding 😃.

References → Python Cookbook