适配器
✳️就是转换,用其他的容器去转换
优先级队列
实现
自己写堆的算法
比较有用的构造函数(迭代器区间构造)
可以有个数组的时候,方便用迭代器去构造
template<class InuPutIterator, class InPutIterator>
Priority_queue(InPutIterator first, InPutIterator last)
{
while (first != last)
{
_con.push_back(*first);
first++;
}
for (int i = 0; i < (_con.size() - 1 - 1) / 2; i++)
{
AdjustDown(i);
}
}
谈deque
✳️vector优点:适合尾插尾删,随机访问
缺点:a.不适合头部或者中部插入删除,效率低,需要挪动数据
b.扩容有一定性能的消耗,还可能存在一定程度的空间浪费
✳️list优点:a.任意位置插入删除效率高(O1)
b.按需申请释放空间
缺点:不支持随机访问
CPU高速缓存命中率低(各节点地址不连续)
✳️结合vector和list的优缺点:deque的双端队列孕育而生
你vector地址是连续的方便访问,但也是你的缺点;
那我如果是一小段小段的呢?
假设一段是10个,满了我就在后面加;
我每段很小,也不会造成大的浪费;
我相当于一段段的小数组;
我为了知道我开了多少个小数组,我还要有个中控数组,实际上是一个指针数组,可以指向每个小数组;
若中控数组满了也要扩容,但扩容代价很低
优点:a.头部和尾部的插入删除效率不错
b.支持随机访问
c.扩容代价很小
d.CPU高速缓存命中率高
缺点:中部的插入删除效率不高
虽然支持随机访问,效率相比vector还是有差距,频繁随机访问要小心
仿函数
✳️仿函数是一个类型,是类型的话我们就可以传参数了!
✳️仿函数可以用来控制代码运行的逻辑我想用什么来比较就比较,想怎么比较就怎么比较!
仿函数/函数对象
template<class T>
struct less
{
bool operator() (T x, T y)
{
return x < y;
}
};
template<class T>
struct greater
{
bool operator() (T x, T y)
{
return x > y;
}
};
打样:
template<class T, class Container=std::vector<T>,class Compare=less<T>>
Compare con_Func;
if (/*_con[parent] <_con[child] */com_Func(_con[parent],_con[child]))//父亲 < 孩子则为真
{
swap(_con[parent], _con[child]);
}
使用:priority_queue<int,vector<int>, greater<int>> pq;
less<int> less_com;
cout << less_com(1, 2) << endl;----单看以为就是函数调用,但这其实是函数对象
greater<int> great_com;
cout << great_com(2, 3) << endl;
✳️仿函数的优势:很多场景,代替函数指针。
使用函数指针
bool ComIntLess(int x, int y)
{
return x < y;
}
template<class T, class Container = vector<T>, class Compare =less<T>>
class priority_queue
{
public:
priority_queue(const Compare& comFunc = Compare())--➡️为了支持函数指针对象的传参我们要写一个函数构造;若不写,则传的函数指针_comFunc为随机值
🌟用函数指针的匿名对象则_conFunc会被初始化为空 指针nullptr,我们再去调用会崩溃
但是我们的仿函数的less/greater可以跑!
:_comFunc(comFunc)
{}
但怎么样才能函数指针跑起来了呢?---则必须要把函数名也给传过去!函数名可以代表函数指针
所以:priority_queue<int, vector<int>, bool(*)(int,int)>pq(ComIntLess );此处pq(ComIntLess)是显示的传参去构造给构造函数去用,去初始化函数指针,此处的ComIntLess是函数的名称;后面就可以玩了!
private:
//Compare _comFunc;----➡️为了方便支持函数指针的传入,就要多一个成员变量
Container _con;
};
sort里的仿函数![请添加图片描述](https://img-blog.csdnimg.cn/b1229e0a640447de8d4040d9a82b3c1f.png)
void testFuntional()
{
vector<int> v
v.push_back(1);
v.push_back(5);
v.push_back(2);
v.push_back(1);
sort(v.begin(),v.end());----默认是升序
若想要降序则需要
//sort(v.begin(),v.end(),greater<int>())----➡️此处greater<int>()需要这样传才行,多了一个(),而我们优先级队列不需要()❓是为什么呢?
✳️我们在优先级队列是作为类的模版参数传过去的,传过去的是类型;
而在sort这里是个函数模版,作为函数的参数,它不需要传类型,是通过实参传给形参自动推导类型!所以传过去的是一个对象,所以我们这里sort用的是一个匿名对象传给函数模版的参数
✳️这里sort是用迭代器作为参数去传的,我们用数组行不行?–当然可以,因为数组的原生指针是天然的随机迭代器!
int a[6] = {1,2,6,3,5,4};
sort(a, a+6);
sort(a, a+6, greater<int>());
✳️什么时候需要我们去写仿函数呢?-----自定义类型!
struct Goods
{
string _name;
double _price;
size_t _saleNum;
✳️ 为了支持比较大小我们需要重载<!
bool operator< (const Goods& g1)const
{
return _price < g._price;
}
因为仿函数less会调用less<T>中的:bool operator()(T& com1, T& com2)
{
return com1 < com2
T被实例化成Goods,则会调用Goods的<比较,所以我们需要在Goods类里面重载<才能支持比较!
}
✳️但我们若是不想以价格来比较大小,则你还能再重载<来解决吗?--不可以,因为参数名相同,无法支持!
则此时用仿函数便可以来解决!但会比较麻烦!实现struct LessPrice;struct GreaterPrice;struct LessSaleNum仿函数
}
实现仿函数:
struct LessPrice
{
bool operator()(const Goods& g1, const Goods& g2) const
{
return g1._price < g2._price;
}
};
struct GreaterPrice
{
bool operator()(const Goods& g1, const Goods& g2) const
{
return g1._price > g2._price;
}
};
struct LessSaleNum
{
bool operator()(const Goods& g1, const Goods& g2) const
{
return g1._saleNum < g2._saleNum;
}
};
Goods gds[4] = { { "苹果", 2.1, 1000}, { "香蕉", 3.0, 200}, { "橙子", 2.2,300}, { "菠萝", 1.5,50} };
sort(gds, gds+4);
sort(gds, gds + 4, LessPrice());-----记得是传对象!所以用的是匿名对象,因为sort是函数模版,不是类模版只用传类型就行,而sort是传参数所以要用匿名对象构造对象传参
sort(gds, gds + 4, GreaterPrice())
sort(gds, gds + 4, LessSaleNum())