📜  双头优先队列

📅  最后修改于: 2021-05-25 00:25:18             🧑  作者: Mango

双头优先级队列支持最大堆(最大优先级队列)和最小堆(最小优先级队列)的操作。双端优先级队列应进行以下操作。

  1. getMax():返回最大元素。
  2. getMin():返回最小元素。
  3. deleteMax():删除最大元素。
  4. deleteMin():删除最小元素。
  5. size():返回元素数。
  6. isEmpty():如果队列为空,则返回true。

我们可以尝试不同的数据结构,例如链表。在链表的情况下,如果我们按排序的顺序维护元素,则所有操作的时间复杂度将变为O(1),但操作insert()则需要O(n)的时间。

我们可以尝试两个堆(最小堆和最大堆)。我们维护最小堆中每个最大堆元素的指针。为了获得最小的元素,我们只需返回根。为了获得最大元素,我们返回最大堆的根。要插入一个元素,我们要同时在minheap和maxheap中插入。主要思想是保持一对一的对应关系,以便可以在O(Log n)时间内完成deleteMin()和deleteMax()。

  1. getMax():O(1)
  2. getMin():O(1)
  3. deleteMax():O(登录n)
  4. deleteMin():O(登录n)
  5. size():O(1)
  6. isEmpty():O(1)

另一种解决方案是使用自平衡二进制搜索树。自平衡BST实现为C++和Java的TreeSet设置。

  1. getMax():O(1)
  2. getMin():O(1)
  3. deleteMax():O(登录n)
  4. deleteMin():O(登录n)
  5. size():O(1)
  6. isEmpty():O(1)

下面是上述方法的实现:

C++
// C++ program to implement double-ended
// priority queue using self balancing BST.
#include 
using namespace std;
  
struct DblEndedPQ {
    set 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 s; 
    DblEndedPQ()
    {
        s= new HashSet();
    }
    // 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 s; 
    public DblEndedPQ()
    {
        s = new HashSet();
    }
      
    // 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


输出:
10
50
40
20

堆和BST解决方案的比较
基于堆的解决方案需要O(n)额外的空间来容纳额外的堆。基于BST的解决方案不需要额外的空间。基于堆的解决方案的优点是缓存友好。