目录
五:用仿函数加容器适配器模拟实现priority_queue
接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧
引言:
在上篇STL中的queue中还有一个叫做优先级队列的知识点
它的结构类似于堆,默认它是大堆,即第一个元素总是他的数据中最大的一个,要想修改为小堆,就要使用仿函数的知识,接下来我们就介绍它
一:priority_queue的介绍
1.优先级队列是一种容器适配器,根据严格的标准,它的第一个元素总是他包含元素中最大的,默认为大堆结构
2.结构类似于堆,在堆中可以随时插入数据,只能检索到最大堆元素(位于顶部的元素)
3.优先级队列被实现为容器适配器,可以封装其他容器来实现自身结构和功能
4.容器deque和vector都满足优先级队列的结构,默认为vector
5.支持随机访问迭代器,始终能保持内部堆结构,容器可以调用算法库中 的make_heap,push_heap和pop_heap来完成对应的操作
二:了解堆结构及对应的各种对应操作
https://blog.csdn.net/Miwll/article/details/136636869?spm=1001.2014.3001.5501
三:priority_queue的接口函数及使用
1.接口函数
2.使用
#include <iostream>
#include <queue>
using namespace std;
int main()
{
//priority_queue<int> p1;
//priority_queue<int, vector<int>, less<int>> p1;//大堆
priority_queue<int, vector<int>, greater<int>> p1;//小堆
p1.push(1);
p1.push(4);
p1.push(2);
p1.push(10);
p1.push(7);
p1.push(13);
while (!p1.empty())
{
cout << p1.top() << " ";
p1.pop();
}
return 0;
}
对于优先级队列他的插入删除数据的效率就是堆插入删除数据的效率,即log(N),效率很高
对于后面的less和greater就是仿函数,接下来就将介绍它
四:仿函数operator()
仿函数就是重载了(),使用的时候像一个函数调用,使用它来替换函数指针
在标准库中常用的仿函数有less和greater来充当比较模板
也可以由我们自己编写自己需要的数据比较形式
常见的greater和less的实现
//仿函数
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;
}
};
void testqueue2()
{
Less<int> less1;//函数对象
cout << less1(1, 4) << endl;
Greater<double> g1;
cout << g1(2.2, 4.4) << endl;
priority_queue<int, vector<int>, Greater<int>> p1;//小堆
p1.push(1);
p1.push(4);
p1.push(2);
p1.push(10);
p1.push(7);
p1.push(13);
while (!p1.empty())
{
cout << p1.top() << " ";
p1.pop();
}
}
对于less和greater不能比较完成的,比如 对于new出来的日期对象,使用less和greater来比较的话,比较的是他们的指针,这就会使结果随机,随意此时我们可以自己定比较规则来比较
struct PDateCompare
{
bool operator()(Date* p1, Date* p2)
{
return *p1 > *p2;
}
};
priority_queue<Date*, vector<Date*>, PDateCompare> q2;
q2.push(new Date(2018, 10, 29));
q2.push(new Date(2018, 10, 28));
q2.push(new Date(2018, 10, 30));
cout << *(q2.top()) << endl;
这里还有特殊的一点是对于库中sort算法和priority_queue中在传参的时候不同
五:用仿函数加容器适配器模拟实现priority_queue
#pragma once
namespace mjw
{
template <class T,class Container=vector<T>,class Compare=Less<T>>
class priority_queue
{
public:
priority_queue()//默认构造
{}
//迭代器区间构造
template<class Inputiterator>
priority_queue(Inputiterator first, Inputiterator last)
:_con(first,last)
{
for (int i = (_con.size() - 2) / 2; i >= 0; --i)//建堆
{
adjust_down(i);
}
}
void adjust_up(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//if(_con[parent]<_con[child])
if (com(_con[parent], _con[child]))
{
std::swap(_con[parent], _con[child]);
child = parent;
parent= (child - 1) / 2;
}
else
{
break;
}
}
}
void adjust_down(int parent)
{
Compare com;
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com( _con[child] , _con[child + 1]))
{
++child;
}
if (com(_con[parent], _con[child]))
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T &x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
}
对于优先级队列的知识就是这了,但在OJ题中很常见题型,需要多加练习掌握