priority_queue 接口使用(仿函数、函数指针解决优先级队列存放自定义类型元素、指针类型元素)
创始人
2024-05-11 17:25:19
0

一、priority_queue  优先队列本质就是 堆

堆: 完全二叉树,任意结点比其孩子结点小->小根堆, 任意结点比其孩子结点大->大根堆,

头文件包含:#include 

二、优先级队列的模板参数列表:

template ,  class Compare = less > class priority_queue;

第二个参数指的是采用什么底层容器进行存储,默认使用vector,因为优先级队列的底层结构就是堆,而堆是一种完全二叉树,完全二叉树就适应这种顺序存储的结构

第三个参数给出的是什么样的比较方式默认采用less方式进行比较从而生成大堆,如果想要使其生成小堆,在模板参数中给出greater。        如果要使用greater 则需要包含头文件#include

三、基本接口的使用

①构造一个空的优先队列 进行插入

void Testpriority_queue01()
{priority_queue  q;q.push(1);q.push(2);q.push(632);q.push(34);q.push(23);q.push(6);q.push(67);q.push(95);q.push(23);cout << q.size() << endl;cout << q.top() << endl;q.pop();q.pop();q.pop();q.pop();cout << q.size() << endl;cout << q.top() << endl;
}

② 利用迭代器来进行区间构造

    使用greater 第一种做法是错误的,没有考虑到第二个参数。

void Testpriority_queue03()
{// priority_queue > q; 错误priority_queue , greater> q;q.push(1);q.push(2);q.push(632);q.push(34);q.push(23);q.push(6);q.push(67);q.push(95);q.push(23);cout << q.size() << endl;cout << q.top() << endl;q.pop();q.pop();q.pop();q.pop();cout << q.size() << endl;cout << q.top() << endl;
}

④ 关于自定义类型数据的插入

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}private:int _year;int _month;int _day;
};void Testpriority_queue04()
{priority_queue q;Date d1(2023, 1, 12);Date d2(2023, 1, 13);Date d3(2023, 1, 11);q.push(d1);q.push(d2);q.push(d3);cout << q.size() << endl;
}

 发生报错,优先队列默认采用less的比较方式来生成一个大堆,可是在这里插入自定义类型Date时,发生了报错,原因显而易见,编译器无法知道数据比较是用Date中的三个参数的哪一个来进行比较。

四、自定义类型数据插入优先级队列发生报错的解决方式

如果编译器无法知道我们的比较方式是如何进行的,那么我们就得告诉编译器如何进行比较

① 【方式一】在Date类中重载比较方式

这种方式易于理解,你不知道怎么比,那我就在Date类中告诉你怎么比较,该用谁来与谁来进行比较。

    bool operator<(const Date& d)const{return _day < d._day;}bool operator>(const Date& d)const{return _day > d._day;}

 ② 【方式二】使用函数指针

那么我写一个函数Compare来给编译器传递我进行比较的方式,传参时将Compare放入q之后的()内,即为q(Compare);

但是这样还不够,如果想要使用函数指针作为函数参数,那么必须把函数类型在优先级队列的模板参数列表中给出来。

优先级队列的模板参数列表上面也提到过,第一个参数为存放元素的类型(Date),第二个参数为什么样的容器来存储(vector),第三个参数就需要传入函数指针的类型

如下为函数指针取别名方式:

typedef bool (*PCOM)(const Date& left, const Date& right);  PCOM为该函数指针的别名

如下为定义优先级队列q:

priority_queue, PCOM> q(Compare);

typedef bool (*PCOM)(const Date& left, const Date& right);
bool Compare(const Date& left, const Date& right)
{return left.GetDay() < right.GetDay();
}void Testpriority_queue05()
{priority_queue, PCOM> q(Compare);Date d1(2023, 1, 12);Date d2(2023, 1, 13);Date d3(2023, 1, 11);q.push(d1);q.push(d2);q.push(d3);cout << q.size() << endl;
}

③【方式三】使用仿函数

所谓的仿函数,就是对()进行运算符重载。使之成为一个能表示函数功能的函数。

为什么是Com?  因为优先级队列的第三个参数为一个class类型,所以需要新实现一个类,类中仅需重载()

 如下在Com类中写入一个()运算符重载函数,说明了Date类内的比较方式,接着在优先级队列进行定义的时候将Com作为模板参数传入即可。

class Com
{
public:bool operator()(const Date& left, const Date& right)const{return left.GetDay() < right.GetDay();}
};void Testpriority_queue06()
{priority_queue, Com> q;Date d1(2023, 1, 12);Date d2(2023, 1, 13);Date d3(2023, 1, 11);q.push(d1);q.push(d2);q.push(d3);cout << q.size() << endl;
}

五、对于优先级队列存放指针的探讨

 如上图,优先级队列中存储元素类型模板参数为Date*,即存储的是Date类型的指针,在默认的优先级队列中,比较方式是按照less的方式进行比较,而指针的本质就是一块地址,这个地址本质就是一串整形十六进制数据,这个数据也能依据less的比较方式来在优先级队列中存储,即该队列就是按照地址的高低大小来进行建堆,地址高即数值大就排在靠近堆顶位置。

可是我的本意是用我指针所指向的内容来进行比较,这里却使用了指针的地址来进行比较,显然没有任何意义,那么如何实现我最初的目的呢?

仿函数的使用:

        提供一个ComPtr的指针比较方式的类,类中传入left,right俩个Date类型的指针,利用这俩个指针来调用Date类中的GetDay()函数来告诉编译器所需要比较的内容具体是什么。

class ComPtr
{
public:bool operator()(const Date* left, const Date* right)const{return left->GetDay() < right->GetDay();}
};
void Testpriority_queue07()
{// 优先级队列中存放的是指针priority_queue, ComPtr> q;Date d1(2023, 1, 12);Date d2(2023, 1, 13);Date d3(2023, 1, 11);q.push(&d1);q.push(&d2);q.push(&d3);
}

 按照指针的内容大小来进行建堆:

 

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...