数据结构与函数使用1:优先队列Priority Queues

本文目的

简单的介绍一下优先队列是什么,有什么用,在写算法面试题的时候如何使用

前置知识点

  1. 堆排序算法
  2. 仿函数:仿函数 function objects
  3. 类与模板
  4. 运算符重载
  5. C++基本语法基础

优先队列Priority Queues简介

实现实时加入或删除堆顶元素,堆顶元素总是优先级最高的
这里的优先级可以是数的最大,向量的长度的最长等等。
优先队列示意图

优先队列的算法原理

就是堆排序算法,加入元素和删除元素的时间复杂度都是O(nlogn),本栏目只介绍优先队列本身的简介和使用,不介绍详细算法。

优先队列的使用

1. 头文件定义

#include<queue>

2. 容器声明

2.1 相关模板定义

查看头文件里面的priority_queue定义是这样的,使用了模板(会自动识别元素内容)

*  @tparam _Tp  Type of element.
*  @tparam _Sequence  Type of underlying sequence, defaults to vector<_Tp>.
*  @tparam _Compare  Comparison function object type, defaults to
*                    less<_Sequence::value_type>.
template<typename _Tp, typename _Sequence = vector<_Tp>,
	   typename _Compare  = less<typename _Sequence::value_type> >
    class priority_queue 

其中function object type是仿函数(也叫函数对象)
模板的定义参数如下

  • 参数1:Typename _Tp,元素类型
  • 参数2:Typename _Sequence,容器,默认是vector
  • 参数3:Typename _Compare,一个比较器用于定义优先级(需要是仿函数),缺省使用less(也就是<运算符)

2.2 默认优先方式的容器声明(大根堆)

模板的后面两个参数都是可以缺省的,也就是只要填写参数类型type即可

#include<queue>
using namespace std;
priority_queue<type> q; //type是指容器类型。比如int,char,string,pair<int,int>等。
priority_queue<int> qint;

2.3 自定义优先级的容器声明

2.3.1仿函数方法

由于模板的第三个参数才是比较器,所以第二个参数也不能省略,一般写vector<type>

#include<queue>
std::priority_queue<type, vector<type>, cmp> q; 
//type是指容器类型。比如int,char,string,pair<int,int>等。
//cmp是比较器,这个比较器后面说怎么写
std::priority_queue<int, vector<int>, greater<int>> minq;//例子:小根堆 

模板参数cmp并不是一个函数(不是函数指针类型),而是一个仿函数。
只是优先队列在比较的时候调用了这个cmp的()运算符而已
注意:a<b其实就是调用了less(a,b),这也是为什么运算符重载也可以修改自定义优先级
所以需要填进去的是一个自定义了()运算符的结构体或者类,这种使用方式一般叫做仿函数
相关内容参考《C++标准库 自修教程与参考手册》8.1.1仿函数可当作排序准则

程序员经常需要把某些class object以已排序的形式置于容器中,当需要以特定的排序规则来排序的时候,仿函数可以派上用场。具体的方式是编写一个类的()运算符重载
举个例子:

using namespace std;
class myless{
    public:
        bool operator() (const int& lhs, const int& rhs) const{
            return lhs < rhs;
        }
};
priority_queue<int,vector<int>,myless> q;

对于优先队列,这里认为右边值是优先值(和sort函数不同,sort函数认为左边是优先值(排序时,左边排前面))
顺带一提,上面成员函数的运算符重载()函数的const是一个声明,表示这个函数不会修改形参,(加个保险,也可以不写)

2.3.2Lambda表达式方法

C++11新引入的方式,提供了Lambda表达式,可以用于给STL算法传递信息。
相关内容参考《C++ Primer Plus》18.4.2 为何使用lambda

  1. 和函数相比:很多程序员认为让定义位于使用的地方附近很有用,便于查看,修改代码的时候,涉及的内容放在一起便于阅读和编辑。比如函数内无法定义其他函数,但是可以定义Lambda表达式,这样就可以更加自由的把定义放在使用的地方旁边。
  2. 和仿函数相比:实现更加简洁,和函数有点像

捕获功能这里不讲,和优先队列没什么关系

3. 其他常见操作

#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int>> minq;//声明队列
minq.push(i);//加入一个元素
minq.top();//堆顶元素
minq.pop();//推出堆顶元素
minq.empty();//是否为空
//没有清空函数,请使用以下方式清空
while(minq.empty())minq.pop();//方式一
minq = priority_queue<int, vector<int>, greater<int>>();//方式二,重新初始化

参考文献

C++标准库 自修教程与参考手册》10.3Priority Queues(优先队列) p453
C++标准库 自修教程与参考手册》8.1.1仿函数可当作排序准则(Sort Criteria) p294

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值