双头优先级队列支持最大堆(最大优先级队列)和最小堆(最小优先级队列)的操作。双端优先级队列应进行以下操作。
- getMax():返回最大元素。
- getMin():返回最小元素。
- deleteMax():删除最大元素。
- deleteMin():删除最小元素。
- size():返回元素数。
- isEmpty():如果队列为空,则返回true。
我们可以尝试不同的数据结构,例如链表。在链表的情况下,如果我们按排序的顺序维护元素,则所有操作的时间复杂度将变为O(1),但操作insert()则需要O(n)的时间。
我们可以尝试两个堆(最小堆和最大堆)。我们维护最小堆中每个最大堆元素的指针。为了获得最小的元素,我们只需返回根。为了获得最大元素,我们返回最大堆的根。要插入一个元素,我们要同时在minheap和maxheap中插入。主要思想是保持一对一的对应关系,以便可以在O(Log n)时间内完成deleteMin()和deleteMax()。
- getMax():O(1)
- getMin():O(1)
- deleteMax():O(登录n)
- deleteMin():O(登录n)
- size():O(1)
- isEmpty():O(1)
另一种解决方案是使用自平衡二进制搜索树。自平衡BST实现为C++和Java的TreeSet设置。
- getMax():O(1)
- getMin():O(1)
- deleteMax():O(登录n)
- deleteMin():O(登录n)
- size():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
输出:
10
50
40
20
堆和BST解决方案的比较
基于堆的解决方案需要O(n)额外的空间来容纳额外的堆。基于BST的解决方案不需要额外的空间。基于堆的解决方案的优点是缓存友好。