📜  双端优先队列

📅  最后修改于: 2021-10-28 02:12:13             🧑  作者: Mango

双端优先级队列支持最大堆(最大优先级队列)和最小堆(最小优先级队列)的操作。双端优先级队列需要执行以下操作。

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

我们可以尝试不同的数据结构,比如链表。在链表的情况下,如果我们按排序顺序维护元素,那么除了操作 insert() 花费 O(n) 时间之外,所有操作的时间复杂度变为 O(1)。
我们可以尝试两个堆(最小堆和最大堆)。我们维护一个指向最小堆中每个最大堆元素的指针。要获得最小元素,我们只需返回 root。为了获得最大元素,我们返回最大堆的根。为了插入一个元素,我们同时插入最小堆和最大堆。主要思想是保持一一对应,使得deleteMin()和deleteMax()可以在O(Log n)时间内完成。

  1. getMax() : O(1)
  2. getMin() : O(1)
  3. deleteMax() : O(Log n)
  4. deleteMin() : O(Log n)
  5. 大小():O(1)
  6. isEmpty() : O(1)

另一种解决方案是使用自平衡二叉搜索树。自平衡 BST 在 C++ 中实现,在Java实现为 TreeSet。

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


Javascript


输出:
10
50
40
20

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程