C++ 优先队列

本文详细介绍了优先队列的概念及其在C++ STL中的实现方式。解释了优先队列的基本操作如push、top、empty等,并展示了如何通过自定义比较函数来创建特定需求的优先队列。此外还介绍了大顶堆与小顶堆的区别。

优先队列

优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。

首先要包含头文件#include<queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队

优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

参考

堆就是如下二叉树,时间负责度是O(Logn)

img

参考

基本操作

  • push
  • top
  • empty
  • size
  • emplace
  • swap

定义:priority_queue<Type, Container, Functional>

Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 listSTL里面默认用的是vector),Functional 就是比较的方式。

当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。

大顶堆与小顶堆

//升序队列,小顶堆(小的在最前面)
 priority_queue <int,vector<int>,greater<int> > q;
 //降序队列,大顶堆(大的再最前面)
 priority_queue <int,vector<int>,less<int> >q;
 
 //greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

自定义比较函数

#include <iostream>
#include <queue>
#include <string>
#include <vector>

using namespace std;

int main() {
  auto cmp = [](int c, int b) -> bool { return c * c < b * b; };
  priority_queue<int, vector<int>, decltype(cmp)> a(cmp);

  a.push(-2);
  a.push(3);
  a.push(1);
  a.push(0);

  while (!a.empty()) {
    cout << a.top() << " ";
    a.pop();
  }
}

输出

3 -2 1 0 
  • 以自定义结构作为元素的优先队列需要单独编写比较函数,可以使用lambda表达式,并用 decltype(cmp) 推导类型
### C++优先队列的使用方法 #### 自定义类型中的 `<` 运算符重载 为了使 `std::priority_queue` 能够处理自定义数据类型,可以通过重载 `<` 运算符来定义比较规则。默认情况下,`std::priority_queue` 使用的是最大堆结构(即顶部元素为最大值),它依赖于元素之间的 `<` 比较操作[^1]。 以下是具体实现方式: 1. **定义自定义类或结构体** 创建一个包含所需字段的数据结构,并在其内部重载 `<` 运算符以指定排序依据。 2. **示例代码** ```cpp #include <iostream> #include <queue> using namespace std; // 定义任务类并重载小于运算符 struct Task { string name; int priority; // 重载 "<" 运算符,使得高优先级的任务排在前面 bool operator<(const Task& other) const { return priority < other.priority; // 高优先级排在前 } }; int main() { // 初始化优先队列,默认是最小堆 (大顶堆),按最高优先级排列 priority_queue<Task> pq; // 插入一些任务到优先队列中 pq.push(Task{"Task A", 3}); pq.push(Task{"Task B", 1}); pq.push(Task{"Task C", 2}); // 输出队列中的任务顺序 while (!pq.empty()) { cout << "Task Name: " << pq.top().name << ", Priority: " << pq.top().priority << endl; pq.pop(); } return 0; } ``` 上述程序通过重载 `<` 运算符实现了基于任务优先级的最大堆排序。 --- #### 不同类型的优先队列初始化 除了支持自定义类型外,`std::priority_queue` 还可以直接用于内置类型(如整数、字符串等)。可以调整其行为以创建升序或降序队列[^2]。 ##### 升序队列 要构建一个升序队列,需显式提供第三个模板参数 `greater<T>` 来改变默认的行为。 ```cpp #include <iostream> #include <queue> using namespace std; int main() { // 构建升序队列 priority_queue<int, vector<int>, greater<int>> minHeap; minHeap.push(5); minHeap.push(1); minHeap.push(7); while (!minHeap.empty()) { cout << minHeap.top() << " "; // 输出最小值 minHeap.pop(); } return 0; } ``` 此代码片段展示了如何利用 `greater<int>` 实现升序队列。 --- ##### 降序队列 对于降序队列,则无需额外设置第三参数,因为这是 `std::priority_queue` 的默认模式。 ```cpp #include <iostream> #include <queue> using namespace std; int main() { // 默认降序队列 priority_queue<int> maxHeap; maxHeap.push(5); maxHeap.push(1); maxHeap.push(7); while (!maxHeap.empty()) { cout << maxHeap.top() << " "; // 输出最大值 maxHeap.pop(); } return 0; } ``` 这段代码体现了标准库中未修改状态下的最大堆特性。 --- ### 总结 C++ 提供了灵活的方式来配置和扩展 `std::priority_queue` 功能。无论是简单的数值型还是复杂的用户定义对象都可以被高效管理。关键是理解底层机制以及适当运用模板参数定制需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值