优先队列(Priority Queue)是一种抽象数据类型,类似于常规的队列或栈,但每个元素都有一个优先级。元素的出队顺序不是按照它们进入队列的顺序,而是根据它们的优先级。优先级最高的元素最先出队。
元素优先级:每个元素都有一个优先级,通常用数值表示,数值越小(或越大)优先级越高。
出队顺序:优先级最高的元素最先出队。
实现方式:优先队列通常通过堆(Heap)数据结构实现,但也可以用其他方式(如有序数组或链表)实现。
插入(Insert/Enqueue):将元素插入队列,并根据其优先级调整队列。
删除(Delete/Dequeue):移除并返回优先级最高的元素。
查看最高优先级元素(Peek):返回优先级最高的元素,但不移除它。
判断是否为空(Is Empty):检查队列是否为空。
堆(Heap):
二叉堆是最常见的实现方式,分为最大堆和最小堆。
插入和删除操作的时间复杂度为 O(logn)O(logn)。
查看最高优先级元素的时间复杂度为 O(1)O(1)。
有序数组或链表:
插入操作的时间复杂度为 O(n)O(n),因为需要维护顺序。
删除操作的时间复杂度为 O(1)O(1)。
平衡二叉搜索树:
插入和删除操作的时间复杂度为 O(logn)O(logn)。
查看最高优先级元素的时间复杂度为 O(1)O(1)。
干货总结:
priority_queue;
type:就是元素的类型
container: 存储元素的容器(必须是数组实现的容器,如vector、deque)
functiolal: 比较规则(可用现有封装,或根据自定义的类对象进行书写比较原则)
//小顶堆
priority_queue ,greater > q;
//大顶堆
priority_queue ,less >q;
//默认大顶堆
priority_queue a;
//pair
priority_queue > a;
pair b(1, 2);
pair c(1, 3);
pair d(2, 5);
a.push(d);
a.push(c);
a.push(b);
while (!a.empty())
{
cout << a.top().first << ' ' << a.top().second << '\n';
a.pop();
}
//输出结果为:
2 5
1 3
1 2
自定义比较方式
当数据类型并不是基本数据类型,而是自定义的数据类型时,就不能用greater或less的比较方式了,而是需要自定义比较方式
举例:
struct task{
string nume;
int id;
int price;
}
有两种自定义比较方式的方法,如下
重载”<”
// 根据任务代价升序排列
// 代价低为优先级高
struct task {
string name;
int id;
int price;
// 重载小于运算符(用于小顶堆)
friend bool operator<(const task& t1, const task& t2) {
return t1.price > t2.price; // 代价低的优先级高
}
};
// 根据任务代价降序排列
// 代价高为优先级高
struct task {
string name;
int id;
int price;
// 重载小于运算符(用于大顶堆)
friend bool operator<(const task& t1, const task& t2) {
return t1.price < t2.price; // 代价高的优先级高
}
};
std::priority_queue
的默认行为std::priority_queue
是一个容器适配器,默认情况下,它使用 std::less
作为比较函数。std::less
的实现是基于 <
运算符的。
默认行为:
std::priority_queue
是一个最大堆(大顶堆)。
它会将较大的元素放在堆顶。
这是通过 std::less
实现的,而 std::less
内部使用的是 <
运算符。
底层逻辑:
如果 a < b
为 true
,则 b
的优先级高于 a
。
因此,默认情况下,std::priority_queue
会按降序排列元素。
<
?虽然小顶堆的逻辑与默认行为相反,但我们仍然重载 <
运算符,而不是 >
运算符。这是因为:
std::priority_queue
只使用 <
运算符:
std::priority_queue
的模板参数中,比较函数默认是 std::less
,它只依赖于 <
运算符。
即使你想实现小顶堆,也需要通过重载 <
来改变默认行为。
如何实现小顶堆:
如果你想实现小顶堆(升序排列),需要让 <
返回 t1.price > t2.price
。
这样,std::priority_queue
会认为较小的元素优先级更高。
// 代价高为优先级,按降序存储
struct compare{
bool operator() (const task &t1,const task&t2){
return t1.price < t2.price;
}
};
//此时优先队列的定义应该如下
priority_queue,compare> pq;
记忆:小根堆是大于号 > ,大根堆是小于号 <