仿函数和优先级队列

适配器

✳️就是转换,用其他的容器去转换

优先级队列

实现

自己写堆的算法

比较有用的构造函数(迭代器区间构造)

可以有个数组的时候,方便用迭代器去构造

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里的仿函数请添加图片描述

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())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值