双端优先级队列支持最大堆(最大优先级队列)和最小堆(最小优先级队列)的操作。双端优先级队列需要执行以下操作。
- getMax() :返回最大元素。
- getMin() :返回最小元素。
- deleteMax() :删除最大元素。
- deleteMin() :删除最小元素。
- size() :返回元素的计数。
- isEmpty() :如果队列为空,则返回 true。
我们可以尝试不同的数据结构,比如链表。在链表的情况下,如果我们按排序顺序维护元素,那么除了操作 insert() 花费 O(n) 时间之外,所有操作的时间复杂度变为 O(1)。
我们可以尝试两个堆(最小堆和最大堆)。我们维护一个指向最小堆中每个最大堆元素的指针。要获得最小元素,我们只需返回 root。为了获得最大元素,我们返回最大堆的根。为了插入一个元素,我们同时插入最小堆和最大堆。主要思想是保持一一对应,使得deleteMin()和deleteMax()可以在O(Log n)时间内完成。
- getMax() : O(1)
- getMin() : O(1)
- deleteMax() : O(Log n)
- deleteMin() : O(Log n)
- 大小():O(1)
- isEmpty() : O(1)
另一种解决方案是使用自平衡二叉搜索树。自平衡 BST 在 C++ 中实现,在Java实现为 TreeSet。
- getMax() : O(1)
- getMin() : O(1)
- deleteMax() : O(Log n)
- deleteMin() : O(Log n)
- 大小():O(1)
- 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 现场工作专业课程和学生竞争性编程现场课程。