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++
#include <bits/stdc++.h>
using namespace std;
struct DblEndedPQ {
set< int > s;
int size()
{
return s.size();
}
bool isEmpty()
{
return (s.size() == 0);
}
void insert( int x)
{
s.insert(x);
}
int getMin()
{
return *(s.begin());
}
int getMax()
{
return *(s.rbegin());
}
void deleteMin()
{
if (s.size() == 0)
return ;
s.erase(s.begin());
}
void deleteMax()
{
if (s.size() == 0)
return ;
auto it = s.end();
it--;
s.erase(it);
}
};
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
import java.util.*;
class solution
{
static class DblEndedPQ {
Set<Integer> s;
DblEndedPQ()
{
s= new HashSet<Integer>();
}
int size()
{
return s.size();
}
boolean isEmpty()
{
return (s.size() == 0 );
}
void insert( int x)
{
s.add(x);
}
int getMin()
{
return Collections.min(s, null );
}
int getMax()
{
return Collections.max(s, null );
}
void deleteMin()
{
if (s.size() == 0 )
return ;
s.remove(Collections.min(s, null ));
}
void deleteMax()
{
if (s.size() == 0 )
return ;
s.remove(Collections.max(s, null ));
}
};
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() );
}
}
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
public class DblEndedPQ
{
HashSet< int > s;
public DblEndedPQ()
{
s = new HashSet< int >();
}
public int size()
{
return s.Count;
}
public bool isEmpty()
{
return (s.Count == 0);
}
public void insert( int x)
{
s.Add(x);
}
public int getMin()
{
return s.Min();
}
public int getMax()
{
return s.Max();
}
public void deleteMin()
{
if (s.Count == 0)
return ;
s.Remove(s.Min());
}
public void deleteMax()
{
if (s.Count == 0)
return ;
s.Remove(s.Max());
}
};
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() );
}
}
|
Javascript
<script>
class DblEndedPQ {
constructor() {
this .s = new Set();
}
size() {
return this .s.size;
}
isEmpty() {
return this .s.size == 0;
}
insert(x) {
this .s.add(x);
}
getMin() {
return Math.min(...Array.from( this .s.values()));
}
getMax() {
return Math.max(...Array.from( this .s.values()));
}
deleteMin() {
if ( this .s.size == 0) return ;
this .s. delete ( this .getMin());
}
deleteMax() {
if ( this .s.size == 0) return ;
this .s. delete ( this .getMax());
}
}
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>" );
</script>
|
Python3
class DblEndedPQ:
def __init__( self ):
self .s = set ()
def size( self ):
return len ( self .s)
def isEmpty( self ):
return len ( self .s) = = 0
def insert( self , x):
self .s.add(x)
def getMin( self ):
return min ( self .s)
def getMax( self ):
return max ( self .s)
def deleteMin( self ):
if len ( self .s) = = 0 :
return
self .s.remove( self .getMin())
def deleteMax( self ):
if len ( self .s) = = 0 :
return
self .s.remove( self .getMax())
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())
|
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.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
20 Mar, 2023
Like Article
Save Article