Open In App

Double ended priority queue

Improve
Improve
Like Article
Like
Save
Share
Report

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. 

  1. getMax() : Returns maximum element.
  2. getMin() : Returns minimum element.
  3. deleteMax() : Deletes maximum element.
  4. deleteMin() : Deletes minimum element.
  5. size() : Returns count of elements.
  6. 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. 

  1. getMax() : O(1)
  2. getMin() : O(1)
  3. deleteMax() : O(Log n)
  4. deleteMin() : O(Log n)
  5. size() : O(1)
  6. 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.

  1. getMax() : O(1)
  2. getMin() : O(1)
  3. deleteMax() : O(Log n)
  4. deleteMin() : O(Log n)
  5. size() : O(1)
  6. 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


Output

10
50
40
20

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.



Last Updated : 20 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads