Double ended priority queue
Last Updated :
20 Mar, 2023
A double ended priority queue supports operations of both max heap (a max priority queue) and min heap (a min priority queue). The following operations are expected from double ended priority queue.
- getMax() : Returns maximum element.
- getMin() : Returns minimum element.
- deleteMax() : Deletes maximum element.
- deleteMin() : Deletes minimum element.
- size() : Returns count of elements.
- isEmpty() : Returns true if the queue is empty.
We can try different data structure like Linked List. In case of linked list, if we maintain elements in sorted order, then time complexity of all operations become O(1) except the operation insert() which takes O(n) time.
We can try two heaps (min heap and max heap). We maintain a pointer of every max heap element in min heap. To get minimum element, we simply return root. To get maximum element, we return root of max heap. To insert an element, we insert in min heap and max heap both. The main idea is to maintain one to one correspondence, so that deleteMin() and deleteMax() can be done in O(Log n) time.
- getMax() : O(1)
- getMin() : O(1)
- deleteMax() : O(Log n)
- deleteMin() : O(Log n)
- size() : O(1)
- isEmpty() : O(1)
Another solution is to use self balancing binary search tree. A self balancing BST is implemented as set in C++ and TreeSet in Java.
- getMax() : O(1)
- getMin() : O(1)
- deleteMax() : O(Log n)
- deleteMin() : O(Log n)
- size() : O(1)
- isEmpty() : O(1)
Below is the implementation of above approach:
C++
// C++ program to implement double-ended
// priority queue using self balancing BST.
#include <bits/stdc++.h>
using namespace std;
struct DblEndedPQ {
set<int> s;
// Returns size of the queue. Works in
// O(1) time
int size()
{
return s.size();
}
// Returns true if queue is empty. Works
// in O(1) time
bool isEmpty()
{
return (s.size() == 0);
}
// Inserts an element. Works in O(Log n)
// time
void insert(int x)
{
s.insert(x);
}
// Returns minimum element. Works in O(1)
// time
int getMin()
{
return *(s.begin());
}
// Returns maximum element. Works in O(1)
// time
int getMax()
{
return *(s.rbegin());
}
// Deletes minimum element. Works in O(Log n)
// time
void deleteMin()
{
if (s.size() == 0)
return;
s.erase(s.begin());
}
// Deletes maximum element. Works in O(Log n)
// time
void deleteMax()
{
if (s.size() == 0)
return;
auto it = s.end();
it--;
s.erase(it);
}
};
// Driver code
int main()
{
DblEndedPQ d;
d.insert(10);
d.insert(50);
d.insert(40);
d.insert(20);
cout << d.getMin() << endl;
cout << d.getMax() << endl;
d.deleteMax();
cout << d.getMax() << endl;
d.deleteMin();
cout << d.getMin() << endl;
return 0;
}
Java
// Java program to implement double-ended
// priority queue using self balancing BST.
import java.util.*;
class solution
{
static class DblEndedPQ {
Set<Integer> s;
DblEndedPQ()
{
s= new HashSet<Integer>();
}
// Returns size of the queue. Works in
// O(1) time
int size()
{
return s.size();
}
// Returns true if queue is empty. Works
// in O(1) time
boolean isEmpty()
{
return (s.size() == 0);
}
// Inserts an element. Works in O(Log n)
// time
void insert(int x)
{
s.add(x);
}
// Returns minimum element. Works in O(1)
// time
int getMin()
{
return Collections.min(s,null);
}
// Returns maximum element. Works in O(1)
// time
int getMax()
{
return Collections.max(s,null);
}
// Deletes minimum element. Works in O(Log n)
// time
void deleteMin()
{
if (s.size() == 0)
return ;
s.remove(Collections.min(s,null));
}
// Deletes maximum element. Works in O(Log n)
// time
void deleteMax()
{
if (s.size() == 0)
return ;
s.remove(Collections.max(s,null));
}
};
// Driver code
public static void main(String args[])
{
DblEndedPQ d= new DblEndedPQ();
d.insert(10);
d.insert(50);
d.insert(40);
d.insert(20);
System.out.println( d.getMin() );
System.out.println(d.getMax() );
d.deleteMax();
System.out.println( d.getMax() );
d.deleteMin();
System.out.println( d.getMin() );
}
}
//contributed by Arnab Kundu
C#
// C# program to implement double-ended
// priority queue using self balancing BST.
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
public class DblEndedPQ
{
HashSet<int> s;
public DblEndedPQ()
{
s = new HashSet<int>();
}
// Returns size of the queue. Works in
// O(1) time
public int size()
{
return s.Count;
}
// Returns true if queue is empty. Works
// in O(1) time
public bool isEmpty()
{
return (s.Count == 0);
}
// Inserts an element. Works in O(Log n)
// time
public void insert(int x)
{
s.Add(x);
}
// Returns minimum element. Works in O(1)
// time
public int getMin()
{
return s.Min();
}
// Returns maximum element. Works in O(1)
// time
public int getMax()
{
return s.Max();
}
// Deletes minimum element. Works in O(Log n)
// time
public void deleteMin()
{
if (s.Count == 0)
return ;
s.Remove(s.Min());
}
// Deletes maximum element. Works in O(Log n)
// time
public void deleteMax()
{
if (s.Count == 0)
return ;
s.Remove(s.Max());
}
};
// Driver code
public static void Main(String[] args)
{
DblEndedPQ d= new DblEndedPQ();
d.insert(10);
d.insert(50);
d.insert(40);
d.insert(20);
Console.WriteLine( d.getMin() );
Console.WriteLine(d.getMax() );
d.deleteMax();
Console.WriteLine( d.getMax() );
d.deleteMin();
Console.WriteLine( d.getMin() );
}
}
// This code contributed by Rajput-Ji
JavaScript
<script>
// JavaScript program to implement double-ended
// priority queue using self balancing BST.
class DblEndedPQ {
constructor() {
this.s = new Set();
}
// Returns size of the queue. Works in
// O(1) time
size() {
return this.s.size;
}
// Returns true if queue is empty. Works
// in O(1) time
isEmpty() {
return this.s.size == 0;
}
// Inserts an element. Works in O(Log n)
// time
insert(x) {
this.s.add(x);
}
// Returns minimum element. Works in O(1)
// time
getMin() {
return Math.min(...Array.from(this.s.values()));
}
// Returns maximum element. Works in O(1)
// time
getMax() {
return Math.max(...Array.from(this.s.values()));
}
// Deletes minimum element. Works in O(Log n)
// time
deleteMin() {
if (this.s.size == 0) return;
this.s.delete(this.getMin());
}
// Deletes maximum element. Works in O(Log n)
// time
deleteMax() {
if (this.s.size == 0) return;
this.s.delete(this.getMax());
}
}
// Driver code
var d = new DblEndedPQ();
d.insert(10);
d.insert(50);
d.insert(40);
d.insert(20);
document.write(d.getMin() + "<br>");
document.write(d.getMax() + "<br>");
d.deleteMax();
document.write(d.getMax() + "<br>");
d.deleteMin();
document.write(d.getMin() + "<br>");
// This code is contributed by rdtank.
</script>
Python3
# Python code for the above approach
class DblEndedPQ:
def __init__(self):
self.s = set()
# Returns size of the queue. Works in
# O(1) time
def size(self):
return len(self.s)
# Returns true if queue is empty. Works
# in O(1) time
def isEmpty(self):
return len(self.s) == 0
# Inserts an element. Works in O(Log n)
# time
def insert(self, x):
self.s.add(x)
# Returns minimum element. Works in O(1)
# time
def getMin(self):
return min(self.s)
# Returns maximum element. Works in O(1)
# time
def getMax(self):
return max(self.s)
# Deletes minimum element. Works in O(Log n)
# time
def deleteMin(self):
if len(self.s) == 0:
return
self.s.remove(self.getMin())
# Deletes maximum element. Works in O(Log n)
# time
def deleteMax(self):
if len(self.s) == 0:
return
self.s.remove(self.getMax())
# Driver code
d = DblEndedPQ()
d.insert(10)
d.insert(50)
d.insert(40)
d.insert(20)
print(d.getMin())
print(d.getMax())
d.deleteMax()
print(d.getMax())
d.deleteMin()
print(d.getMin())
# This code is contributed by codebraxnzt
Comparison of Heap and BST solutions
Heap based solution requires O(n) extra space for an extra heap. BST based solution does not require extra space. The advantage of heap based solution is cache friendly.
Similar Reads
Priority Queue using Doubly Linked List
Given Nodes with their priority, implement a priority queue using doubly linked list. Prerequisite : Priority Queue push(): This function is used to insert a new data into the queue.pop(): This function removes the element with the lowest priority value from the queue.peek() / top(): This function i
11 min read
Indexed Priority Queue with Implementation
Priority queue is a data structure in which data is stored on basis of its priority. In an Indexed Priority Queue, data is stored just like standard priority queue and along with this, the value of a data can be updated using its key. It is called "indexed" because a hash map can be used to store th
8 min read
Priority Queue using Linked List
Implement Priority Queue using Linked Lists. The Linked List should be so created so that the highest priority ( priority is assigned from 0 to n-1 where n is the number of elements, where 0 means the highest priority and n-1 being the least ) element is always at the head of the list. The list is a
11 min read
Priority Queue in Python
A priority queue is like a regular queue, but each item has a priority. Instead of being served in the order they arrive, items with higher priority are served first. For example, In airlines, baggage labeled âBusinessâ or âFirst Classâ usually arrives before the rest. Key properties of priority que
3 min read
Priority Queue using Binary Heap
What is a Priority Queue ?Priority Queue is an extension of the queue with the following properties: Every item has a priority associated with it.An element with high priority is dequeued before an element with low priority.If two elements have the same priority, they are served according to their o
15+ min read
Applications of Priority Queue
A Priority Queue is different from a normal queue, because instead of being a "first-in-first-out", values come out in order by priority. It is an abstract data type that captures the idea of a container whose elements have "priorities" attached to them. An element of highest priority always appears
2 min read
Python | Queue using Doubly Linked List
A Queue is a collection of objects that are inserted and removed using First in First out Principle(FIFO). Insertion is done at the back(Rear) of the Queue and elements are accessed and deleted from first(Front) location in the queue. Queue Operations:1. enqueue() : Adds element to the back of Queue
3 min read
Thread Priority in Android
Every thread in a process has a Priority. They are in the range of 1 to 10. Threads are scheduled according to their priorities with the help of a Thread Scheduler. There can be 3 priority constant set for a Thread which are:MIN_PRIORITY which equals to 1MAX_PRIORITY which equals to 10NORM_PRIORITY
3 min read
Turn a Queue into a Priority Queue
What is Queue?Queue is an abstract data type that is open at both ends. One end is always used to insert data (enqueue) which is basically the rear/back/tail end and the other which is the front end is used to remove data (dequeue). Queue follows First-In-First-Out (FIFO) methodology, i.e., "the dat
9 min read
Difference between Circular Queue and Priority Queue
Queues are fundamental data structures that are used to store and manage a collection of elements. While both circular queues and priority queues are types of queues, they have distinct characteristics and applications. This article will explore the key differences between circular queues and priori
4 min read