这里写目录标题

  • 一.优先级队列
    • 1.优先级队列的介绍
    • 2.priority_queue的定义与使用
  • 二.仿函数/函数对象
  • 三.优先级队列的模拟实现

一.优先级队列

1.优先级队列的介绍

1)注意优先级队列和队列不是一个东西,队列是容器,优先级队列是一种容器适配器,不提供迭代器。(了解容器适配器,请点击这篇文章:【C++】容器适配器)

2)优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue

3)优先级队列:
less->大堆,默认优先级高的元素先输出;
greater->小堆,默认优先级小的元素先输出。

4)注意priority_queue默认构建大堆。原因:运行下面的代码,向堆中插入数据后,默认使用向上调整算法,构建大堆,我们依次取top(栈顶元素),输出的结果是降序,即优先级高的元素先输出。

对堆的数据结构还不熟悉或忘了的宝子们可以点击这篇博客进行学习——>【数据结构】堆的实现

2.priority_queue的定义与使用

priority_queue的各个成员函数及其功能如下:

方式一:不指定底层容器和内部需要构造的堆结构。(默认使用vector作为底层容器,构造大堆结构)

priority_queue<int> pq;

方式二:使用vector作为底层容器,内部构造大堆结构。

priority_queue<int,vector<int>,less<int>> pq1;

方式三:使用vector作为底层容器,内部构造小堆结构。[使用方式如下图]

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

二.仿函数/函数对象

1.在C语言中,我们是用函数指针实现函数的传递。但是函数指针的形式有些累赘,那么C++引入了仿函数(又称函数对象)。
仿函数(函数对象)的定义:如果我们在一个类中重载了()运算符。那么该类的实例化对象就可以像调用函数一样去调用。具体实现过程的代码如下:

#include<iostream>
using namespace std;
//仿函数/函数对象
namespace nn
{template<class T>class less//<{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater//>{public:bool operator()(const T& x, const T& y){return x > y;}};
}
//函数对象传参:需要定义多参数模板
template<class T,class Compare>
void bubble_sort(T* a, int n,Compare com)
{for (int i = 0; i < n-1; i++){int flag = 0;for (int j = 1; j < n - i; j++){if (com(a[j], a[j-1]))//com是类的实例化对象,com()相当于运算符重载函数,operator>,operator<{swap(a[j-1], a[j]);flag = 1;}}if (flag == 0){break;}}
}
int main()
{nn::less<int> lessFunc;//我们在less类中重载了()运算符,就可以用该类的实例化对象当作函数来使用nn::greater<int> greaterFunc;//我们在less类中重载了()运算符,就可以用该类的实例化对象当作函数来使用int a[] = { 2, 3, 4, 5, 6, 1, 2, 4, 9 };bubble_sort(a, sizeof(a) / sizeof(a[0]), lessFunc);for (auto e : a){cout << e << " ";}cout << endl;bubble_sort(a, sizeof(a) / sizeof(a[0]), greaterFunc);for (auto e : a){cout << e << " ";}cout << endl;return 0;
}

2.上面的less和greater类是我们自己实现的,库中也有对应的类,头文件是functional,这里给个C++标准库less类的解释。

三.优先级队列的模拟实现

priority_queue的底层实际上是堆结构,实现priority_queue之前,我们得先知道堆这个数据结构的算法,详情请点击【数据结构】堆的实现

  • 升序建大堆——>小于号——>less
  • 降序建小堆——>大于号——>greater
#define _CRT_SECURE_NO_WARNINGS 1
namespace nn
{template<class T>class less//<{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater//>{public:bool operator()(const T& x, const T& y){return x > y;}};//多参数模板:数据类型,容器,函数对象/仿函数template<class T, class Container = vector<T>,class Compare = less<T>>//优先级队列默认建大堆,less——>小于号class priority_queue{public://构造函数priority_queue(){}//迭代器构造template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first,last){//向下调整建堆,时间复杂度O(N)for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; i--){adjust_down(i);}}void adjust_up(size_t child){Compare com;//定义一个仿函数对象,可以用作函数size_t parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if(com(_con[parent],_con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjust_down(size_t parent){Compare com;size_t minchild = parent * 2 + 1;while (minchild < _con.size()){if (minchild + 1 < _con.size() && com(_con[minchild],_con[minchild + 1])){minchild = minchild + 1;}//if (_con[parent] < _con[minchild])if(com(_con[parent],_con[minchild])){swap(_con[minchild], _con[parent]);parent = minchild;minchild = 2 * parent + 1;}else{break;}}}//一边push一边向上调整void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}//pop的是栈顶元素,交换栈顶元素和最后一个元素,删除最后一个元素,然后用向下调整算法(时间复杂度logN,因为已经满足左右子树是堆,所以可以直接用向下调整算法)void pop(){swap(_con[0],_con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top() const{return _con[0];}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供>,<的运算符重载。

class Date
{public:Date(int year = 1900, int month = 1, int day = 1):_year(year),_month(month),_day(day){}//自定义类需要自己重载>,<等运算符bool operator<(const Date& d) const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream& operator<<(ostream& _cout, const Date& d){_cout << d._year << "-" << d._month << "-" << d._day;return _cout;}
private:int _year;int _month;int _day;
};//对Date*重载两个类
struct PDateLess
{bool operator()(const Date* x, const Date* y){return *x < *y;}
};
struct PDateGreater
{bool operator()(const Date* x, const Date* y){return *x > *y;}
};
void TestPriorityQueue()
{// 大堆,需要用户在自定义类型中提供<的重载priority_queue<Date> q1;q1.push(Date(2018, 10, 29));//匿名对象q1.push(Date(2018, 10, 28));q1.push(Date(2018, 10, 30));cout << q1.top() << endl;// 如果要创建小堆,需要用户提供>的重载priority_queue<Date, vector<Date>, greater<Date>> q2;q2.push(Date(2018, 10, 29));q2.push(Date(2018, 10, 28));q2.push(Date(2018, 10, 30));cout << q2.top() << endl;//那如果改成传日期对象的地址呢?//答:重新重载两个类比较日期的大小priority_queue<Date*, vector<Date*>, PDateLess> q3;q3.push(new Date(2018, 10, 29));//匿名对象,new返回的是动态开辟空间的地址q3.push(new Date(2018, 10, 28));q3.push(new Date(2018, 10, 30));cout << *q3.top() << endl;priority_queue<Date*, vector<Date*>, PDateGreater> q4;q4.push(new Date(2018, 10, 29));q4.push(new Date(2018, 10, 28));q4.push(new Date(2018, 10, 30));cout << *q4.top() << endl;
}

【C++】优先级队列priority_queue/仿函数(函数对象)相关推荐

  1. 【C++】优先级队列priority_queue仿函数

    这里先简单介绍一下优先级队列priority_queue:优先队列是一种容器适配器,默认的情况下,如果没有为特定的priority_queue类实例化指容器类,则使用vector (deque 也是可 ...

  2. 6-5-3:STL之stack和queue——优先级队列-priority_queue(堆)的基本使用和模拟实现以及仿函数

    文章目录 一:优先级队列-priority_queue(堆) (1)基本使用 (2)模拟实现 二:仿函数 (1)仿函数是什么 (2)使用仿函数完成大顶堆和小顶堆的构建 一:优先级队列-priority ...

  3. 优先级队列priority_queue

    优先级队列priority_queue 优先级队列是一个拥有权值的queue,其内部元素按照元素的权值排列.权值较高者排在最前优先出队.其中缺省情况下系统是通过一个max-heap以堆实现完成排序特性 ...

  4. (P85)stl(十三):容器适配器,stack,queue,优先级队列priority_queue,make_heap

    文章目录 1.容器适配器 2.stack 3.queue 4.优先级队列priority_queue 5.make_heap 6.set 1.容器适配器 利用基本容器构造的容器,称之为容器适配器 基本 ...

  5. C++ STL 学习笔记__(6)优先级队列priority_queue基本操作

    10.2.7优先级队列priority_queue v  最大值优先级队列.最小值优先级队列 v  优先级队列适配器 STL priority_queue v  用来开发一些特殊的应用,请对stl的类 ...

  6. STL学习系列七:优先级队列priority_queue容器

    1.简介 最大值优先级队列.最小值优先级队列 优先级队列适配器 STL priority_queue 用来开发一些特殊的应用,请对stl的类库,多做扩展性学习 这里给个例子: #include< ...

  7. 详解优先级队列priority_queue(应用+模拟实现)

    优先级队列的概念 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元 素 ...

  8. C++ 优先级队列 priority_queue

    优先级队列(priority_queue)是一种容器适配器(container adaptor).它要求容器具有front.push_back.pop_back等操作,并且容器具有随机访问的能力,故优 ...

  9. 仿函数 ( 函数对象 ) 详解

    在C语言中我们是如何实现函数的传递呢? 没错就是函数指针! template<class T> void Say(T a) {cout << a << endl; ...

最新文章

  1. 签约华佗致力精准饮食 谋定·健康中国-李喜贵:健康干预治未病
  2. sqlserver操作geography方法
  3. 知乎高赞:有哪些你看了以后大呼过瘾的数据分析书?
  4. Spring @Service批注
  5. 简易呼吸灯c语言程序,51单片机(呼吸灯)C语言版
  6. 3dmax2016的破解和安装
  7. 计算机管理十大突出问题,TPM设备管理十大问题
  8. 数学常识--数学符号常识
  9. 【mac】nvm 的安装和使用,解决mac重启node not found,每次都得source ~/.bash_profile
  10. 用flutter_html_view打开大成的cdsn的web网页详细操作
  11. 35个Python实战项目,完整源代码!
  12. 【Python入门】出发吧
  13. 智慧路灯行业市场规模有多大?
  14. 广州哪个大学大一计算机学ps,紧急!广东12所“野鸡大学”名单曝光!广州人千万别上当!...
  15. 联合办公空间会员需要保险吗?
  16. .net core/5/6/7中WPF如何优雅的开始开发
  17. efi shell的英文介绍_请问电脑开机后显示英文字母efi shell version 2.31是什么意思...
  18. 航天信息计算机设备如何入账,​收到航天信息发票账务处理
  19. 非常好用的在线编程网站
  20. python网易云音乐下载_GUI图形化界面

热门文章

  1. 初识 Swift编程语言(中文版)
  2. 黄冈师范计算机学院在哪个校区,2021黄冈师范学院有几个校区,新生在哪个校区及分配规则...
  3. diskgenius创建efi分区_Windows重建EFI引导启动分区(esp分区)
  4. C语言union联合体中不同类型变量读取同一地址数据问题
  5. word自动生成目录后,序号和标题之间有空格,如何删除空格
  6. 大数据日知录理解(1)
  7. 首小时单品破亿、总销售破1.9亿,德施曼双十一首日再获全网第一
  8. 页面滚动时触发动画特效 wow.js + Animate.css
  9. JAVA宠物领养系统计算机毕业设计Mybatis+系统+数据库+调试部署
  10. c1000k 高性能服务器构建技术,C1000K高性能服务器构建技术 (52页)-原创力文档...