priority_queue
1.priirity_queue优先级队列是一种容器适配器。
2.priority_queue底层的数据结构是vector,通过堆算法来来排序从而实现优先级队列
3.默认情况下,priority_queue是大堆(降序)
模拟实现代码如下:
//PriorityQueue.h #pragma once #includenamespace yqx { template class Less { public: bool operator()(const T& x, const T& y)const { return x < y; } }; template class Greater { public: bool operator()(const T& x, const T& y)const { return x > y; } }; template ,class Compar = Less > class priority_queue { public: priority_queue() { } template //迭代器范围初始化 priority_queue(InputIterator first, InputIterator last) { //将数据插入 while (first != last) { _con.push_back(*first); ++first; } //建堆 for (int i = (_con.size() - 2) / 2; i >= 0; --i) { AdjustDown(i); } } size_t size()const { return _con.size(); } void Adjustup(size_t child) { Compar com;//仿函数定义对象 size_t parent = (child - 1) / 2; while (child > 0) { if (com(_con[parent],_con[child])) { swap(_con[child], _con[parent]); child = parent; parent = (child - 1) / 2; } else break; } } void AdjustDown(size_t parent) { Compar com;//仿函数定义对象 size_t child = 2 * parent + 1; while (child<_con.size()) { if (child + 1<_con.size() && com(_con[child], _con[child + 1])) { child++; } if (com(_con[parent] , _con[child])) { swap(_con[parent], _con[child]); parent = child; child = 2 * parent + 1; } else break; } } void push(const T& x) { _con.push_back(x); Adjustup(_con.size() - 1); } void pop() { swap(_con[0], _con[_con.size() - 1]); _con.pop_back(); AdjustDown(0); } const T& top() { return _con[0]; } bool empty() { return _con.empty(); } private: Container _con; }; } //Test.cpp(测试用例) #include using namespace std; #include #include #include #include"PriorityQueue.h" //使用库函数中的priority_queue //int main() //{ // priority_queue , less > lt; // lt.push(2); // lt.push(1); // lt.push(3); // lt.push(5); // lt.push(4); // while (!lt.empty()) // { // cout << lt.top() << " "; // lt.pop(); // } // cout << endl; // return 0; //} //打印容器中的元素 //tpyename的使用会在代码块下边做以简单介绍 template void PrintContainer(const Container& p) { typename Container::const_iterator it = p.begin(); while (it != p.end()) { cout << *it << " "; ++it; } cout << endl; } class Date { public: Date(int year = 1990,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); } friend ostream& operator<<(ostream& out, const Date& d); friend class PDateLess; private: int _year; int _month; int _day; }; ostream& operator<<(ostream& out, const Date& d)//日期类输出重载 { cout << d._year << "-" << d._month << "-" << d._day; return out; } class PDateLess { public: bool operator()(const Date* p1, const Date* p2)const { return *p1 < *p2; } }; int main() { //将类作为priority_queue初始化构造的元素 //使用类的指针来构造priority_queue yqx::priority_queue ,PDateLess> lt; lt.push(new Date(2020, 12, 23)); lt.push(new Date(2020, 11, 25)); lt.push(new Date(2020, 12, 24)); lt.push(new Date(2020, 11, 22)); cout << *lt.top() << endl; lt.pop(); return 0; }
关键字typename的使用
//typename的使用 templatevoid PrintContainer(const Container& p) { Container::const_iterator it = p.begin(); while (it != p.end()) { cout << *it << " "; ++it; } cout << endl; }
对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了 typename 关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。
因此,如果你想直接告诉编译器 T::const_iterator 是类型而不是变量,只需用 typename修饰:
typename Container::const_iterator it = p.begin(); typename Container::const_iterator it (p.begin());
加上typename之后,编译器就会知道这是个类型,而不再需要等到实例化时期才能确定。
初识仿函数
仿函数(Functor)又称为函数对象(Function Object)是一个能行使函数功能的类。仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载operator()运算符。因为调用仿函数,实际上就是通过类对象调用重载后的operator()运算符。
如果要将某种“操作”当做算法的参数,一般有两种方法:
(1)先将该“操作”设计为一个函数,再将函数指针当做算法的一个参数。
(2)将该“操作”设计为一个仿函数(就语言层面而言是个class),再以该仿函数产生一个对象,并以此对象作为算法的一个参数。
很明显第二种方法会更优秀,在我们写代码时有时会发现有些功能代码,会不断地被使用。为了复用这些代码,实现为一个公共的函数是一个解决方法。不过函数用到的一些变量,可能是公共的全局变量。引入全局变量,容易出现同名冲突,不方便维护。
仿函数的优点:
仿函数是模板函数,.在同一时间里,由某个仿函数所代表的单一函数,可能有不同的状态,可以根据不同的类型代表不同的状态 仿函数是模板函数,所以仿函数即使定义相同,也可能有不同的类型 仿函数是模板函数,仿函数通常比一般函数速度慢 仿函数使程序代码变简单,仿函数在一定程度上使代码更通用,本质上简化了代码



