优先队列priority_queue 用法详解

本文介绍了优先队列的基本概念及其在C++ STL中的实现方式。详细解释了如何通过不同参数设置实现大顶堆或小顶堆,并提供了自定义优先级的示例代码。

优先级队列默认less 大数优先。

priority_queue<Type, Container, Functional>
其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。
Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.
STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,
优先队列就是大顶堆,队头元素最大。

优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序

每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储。

例如:我们常用的操作就是对数据排序,优先队列默认的是数据大的优先级高

所以我们无论按照什么顺序push一堆数,最终在队列里总是top出最大的元素。

用法:

示例:将元素5,3,2,4,6依次push到优先队列中,print其输出。

1. 标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。

priority_queue<int> pq;

通过<操作符可知在整数中元素大的优先级高。
故示例1中输出结果为: 6 5 4 3 2

 

2. 数据越小,优先级越高

priority_queue<int, vector<int>, greater<int> >pq; 

其中
第二个参数为容器类型。
第二个参数为比较函数。
故示例2中输出结果为:2 3 4 5 6

3. 自定义优先级,重载比较符号

重载默认的 < 符号

复制代码
struct node
{
    friend bool operator< (node n1, node n2)
    {
        return n1.priority < n2.priority;
    }
    int priority;
    int value;
}; 
复制代码

这时,需要为每个元素自定义一个优先级。

注:重载>号会编译出错,因为标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
而且自定义类型的<操作符与>操作符并无直接联系

代码:

复制代码
 1 #include<iostream>
 2 #include<functional>
 3 #include<queue>
 4 using Namespace stdnamespace std;
 5 struct node
 6 {
 7     friend bool operator< (node n1, node n2)
 8     {
 9         return n1.priority < n2.priority;
10     }
11     int priority;
12     int value;
13 };
14 int main()
15 {
16     const int len = 5;
17     int i;
18     int a[len] = {3,5,9,6,2};
19     //示例1
20     priority_queue<int> qi;
21     for(i = 0; i < len; i++)
22         qi.push(a[i]);
23     for(i = 0; i < len; i++)
24     {
25         cout<<qi.top()<<" ";
26         qi.pop();
27     }
28     cout<<endl;
29     //示例2
30     priority_queue<int, vector<int>, greater<int> >qi2;
31     for(i = 0; i < len; i++)
32         qi2.push(a[i]);
33     for(i = 0; i < len; i++)
34     {
35         cout<<qi2.top()<<" ";
36         qi2.pop();
37     }
38     cout<<endl;
39     //示例3
40     priority_queue<node> qn;
41     node b[len];
42     b[0].priority = 6; b[0].value = 1; 
43     b[1].priority = 9; b[1].value = 5; 
44     b[2].priority = 2; b[2].value = 3; 
45     b[3].priority = 8; b[3].value = 2; 
46     b[4].priority = 1; b[4].value = 4; 
47 
48     for(i = 0; i < len; i++)
49         qn.push(b[i]);
50     cout<<"优先级"<<'\t'<<""<<endl;
51     for(i = 0; i < len; i++)
52     {
53         cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;
54         qn.pop();
55     }
56     return 0;
57 }
复制代码

转载自:vvilp,有改动


<think>好的,用户想了解C++中优先队列priority_queue用法,包括使用方法、示例、语法和解释。我需要根据提供的引用资料来整理回答。 首先,要确定priority_queue的基本用法。根据引用[1],priority_queue在C++中需要包含头文件,但引用[4]提到头文件是<queue>,而引用[5]的例子也使用了#include <queue>,所以应该纠正引用[4]中的头文件错误。基本语法是priority_queue<类型, 容器, 比较函数>,默认使用vector作为容器,比较函数默认是less,形成大顶堆。 接下来,自定义比较函数部分。引用[1]和[2]提到可以使用仿函数或decltype来指定比较函数。例如,仿函数需要重载operator(),并且注意比较的逻辑,比如引用[2]中的例子用*a > *b实现小顶堆。同时,引用[3]展示了使用less和greater来创建大顶堆和小顶堆的不同方法。 然后,示例部分。引用[5]提供了基本的示例代码,使用默认的priority_queue,输出是按大顶堆排列。需要补充小顶堆的示例,以及使用自定义比较函数的例子,比如结构体或指针的比较。 需要注意语法中的细节,比如模板参数的位置,使用decltype时需要配合构造函数传递比较函数对象,如引用[1]中的例子。此外,在C++17之后可能可以省略模板参数,但为了兼容性最好明确指定。 用户可能的问题包括如何调整堆的类型、自定义数据结构的比较方法,以及为什么使用仿函数。需要确保回答覆盖这些点,并引用正确的资料。例如,引用[3]解释了大顶堆和小顶堆的不同声明方式,引用[2]展示了指针类型的比较方法。 最后,生成相关问题,可能涉及性能、应用场景或与其他容器的比较。需要确保问题与主题相关,并基于引用内容,比如比较函数的实现方式或优先队列的时间复杂度。 总结回答结构:基本用法、自定义比较函数的三种方法、示例代码、注意事项,然后相关问题。确保每个部分都有对应的引用支持,并正确标注引用标识。</think>### C++中priority_queue用法详解 #### 1. 基本语法与默认行为 优先队列`priority_queue`是C++标准库提供的**堆数据结构**实现,包含在头文件`<queue>`中[^4][^5]。其默认行为为**大顶堆**(降序排列),声明语法为: ```cpp priority_queue<T, Container, Compare> pq; ``` - `T`:元素类型(如`int`、`string`) - `Container`:底层容器(默认`vector<T>`) - `Compare`:比较函数(默认`less<T>`,即大顶堆) 例如,创建整数大顶堆: ```cpp priority_queue<int> pq; // 等价于 priority_queue<int, vector<int>, less<int>> ``` #### 2. 自定义比较函数方法 ##### (1) 使用内置函数对象 通过`greater<T>`创建**小顶堆**(升序排列): ```cpp priority_queue<int, vector<int>, greater<int>> min_heap; // 小顶堆[^3] ``` ##### (2) 自定义仿函数(推荐) 定义含`operator()`的类,例如处理指针类型: ```cpp class Compare { public: bool operator()(int* a, int* b) { return *a > *b; // 小顶堆比较规则[^2] } }; priority_queue<int*, vector<int*>, Compare> ptr_heap; ``` ##### (3) 使用decltype与lambda表达式(C++11+) 适用于需要动态比较逻辑的场景: ```cpp auto cmp = [](int a, int b) { return a > b; }; priority_queue<int, vector<int>, decltype(cmp)> custom_heap(cmp); // 需传递lambda对象[^1] ``` #### 3. 完整示例代码 ##### 示例1:默认大顶堆 ```cpp #include <iostream> #include <queue> using namespace std; int main() { int arr[] = {3, 1, 4, 1, 5}; priority_queue<int> pq; for (int x : arr) pq.push(x); while (!pq.empty()) { cout << pq.top() << " "; // 输出:5 4 3 1 1 pq.pop(); } return 0; } ``` ##### 示例2:结构体排序 ```cpp struct Node { int value; Node(int v) : value(v) {} }; struct NodeCompare { bool operator()(const Node& a, const Node& b) { return a.value < b.value; // 按value降序排列 } }; priority_queue<Node, vector<Node>, NodeCompare> node_heap; ``` #### 4. 关键注意事项 1. **时间复杂度**:插入(`push`)和删除堆顶(`pop`)操作均为$O(\log n)$,访问堆顶(`top`)为$O(1)$[^3] 2. **元素类型要求**:比较函数需满足**严格弱序**关系 3. **容器选择**:底层容器必须支持随机访问迭代器(如`vector`或`deque`)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值