8-6 算法 8-7 仿函数 8-8 适配器

算法

一:算法概述: 
    比如:查找,排序等等;数十甚至上百个算法;数量不断上涨;
    算法的前两个形参的类型,一般都是迭代器类型,用来表示容器中的元素的一个区间;

算法名(iterbg,itered) ,传递进去的应该是 一个前闭后开的区间[ begin()  ,end() );
前闭后开的区间的好处一般认为有两条:
       a)算法只要判断迭代器只要等于后边这个开区间,那么就表示迭代结束;
       b)如果第一个形参等于第二个形参,也就是itergb == itered,那么就表示是个空区间;

 

算法:是一种搭配迭代器来使用的全局函数;算法跟具体容器没关联,只跟迭代器有关联;只需要根据迭代器来开发算法,不需要理会具体容器,从而增加了算法代码开发的弹性;
算法这种泛型编程方式,增加灵活性,但是缺失了直观性;某些数据结构(某些容器的迭代器)和算法之间的兼容性也不是那么的好;
stl中到底有哪些算法:《c++标准库 第二版》 11.2.2 “算法分门别类”

namespace _nmsp1
{			
	void func()
	{			
		list<int> mylist = { 100,200,300 };
		list<int>::iterator iterbg = mylist.begin(); 
		list<int>::iterator itered = mylist.end(); //最后一个元素的下一个位置;
	   		 
		return;	
	}
}

二:算法内部一些处理
算法会根据传递进来的迭代器来分析出迭代器种类(五种之一),不同的种类的迭代器,算法会有不同的处理,要编写不同的代码来 应对;
这种编写不同的代码来处理不同种类的迭代器,能够直接影响到算法的执行效率;(效率是一个很重要的指标)
这也就是stl内部为什么要给这些迭代器做一个分类的目的
        

三:一些典型算法使用范例
    算法头文件要包含进来:#include <algorithm>
   (3.1)for_each:未归类知识点8节

namespace _nmsp3
{
	
	//template<class InputIterator,class Function>
	//Function for_each(InputIterator first, InputIterator last, Function f)
	//{
	//	for (; first != last; ++first) //10,20,30,40,50
	//	{
	//		f(*first);
	//	}
	//	return f;
	//}
	//这段代码表明2个问题:
	//a)算法区分迭代器种类,这个种类决定着某些算法的效率;InputIterator


	void myfunc(int i) //参数类型是容器中的元素类型
	{
		cout << i << endl;
	}

	void func()
	{
		vector<int> myvector = { 10,20,30,40,50 };
		//for_each工作原理:不断的迭代给进来的两个迭代器之间的元素,然后拿到这个元素,以这个元素为实参来调用myfunc(元素);
		for_each(myvector.begin(), myvector.end(), myfunc); //myfunc是可调用对象:未归类知识点7节


	}
}

三:一些典型算法使用范例
当有成员函数和全局函数(算法)同时存在时,优先考虑使用同名的成员函数,如果没有同名的成员函数,才考虑使用这些算法;

namespace _nmsp4
{

	//(3.2)find
	//(3.3)find_if
	void func()
	{
		vector<int> myvector = { 10,20,30,40,50 };
		vector<int>::iterator finditer = find(myvector.begin(), myvector.end(), 400);
		if (finditer != myvector.end()) //判断是否等于find的第二个参数,等于就没找到,不等于就找到了
		{
			//找到了
		}
		else
		{
			//没找到
		}

		map<int, string> mymap;
		mymap.insert(std::make_pair(1, "老王"));
		mymap.insert(std::make_pair(2, "老李"));
		auto iter = mymap.find(2);  //优先使用自己的成员函数
		if (iter != mymap.end())
		{
			//找到
			printf("编号为%d,名字为%s\n", iter->first, iter->second.c_str());
		}
		//find_if演示
		auto result = find_if(myvector.begin(), myvector.end(), [](int val) //lambda表达式也是可调用对象
		{
			if (val > 15)
				return true;  //停止遍历
			return false;
		});
		if (result == myvector.end())
		{
			cout << "没找到" << endl;
		}
		else
		{
			cout << "找到了,结果为:" << *result << endl;
		}
	}
}
namespace _nmsp5
{
	//(3.4)sort
	bool myfunc(int i, int j)
	{
		//return i < j;  //从小到大排序
		return i > j; //从大到小排序
	}
	class A
	{
	public:
		bool operator()(int i, int j)
		{
			return i > j;
		}
	};

	void func()
	{
		vector<int> myvector = { 50,15,80,30,46 };
		//sort(myvector.begin(), myvector.end()); //缺省按照从小到的顺序排列的,15,30,46,50,80
		//sort(myvector.begin(), myvector.begin() + 3);//只有前三个元素参与排序:15,50,80, 30,46
		//若要从大到小排序,我们可以写自定义的比较函数,这个函数是返回bool;
		//sort(myvector.begin(), myvector.end(), myfunc);
		/*A mya;
		sort(myvector.begin(), myvector.end(), mya);
		for (auto iter = myvector.begin(); iter != myvector.end() ;++iter)
		{
			cout << *iter << endl;
		}*/

		//试试list
		list<int> mylist = { 50,15,80,30,46 };
		//sort(mylist.begin(), mylist.end(), myfunc); //list不支持sort算法
		mylist.sort(myfunc);
		for (auto iter = mylist.begin(); iter != mylist.end(); ++iter)
		{
			cout << *iter << endl;
		}

		map<int, string> mymap;
		mymap.insert(std::make_pair(50, "老王"));
		mymap.insert(std::make_pair(15, "老李"));
		mymap.insert(std::make_pair(80, "老赵"));
		//sort(mymap.begin(), mymap.end()); //不让排序编译报错;

		unordered_set<int> myset = { 50,15,80,30,46 };
		//sort(myset.begin(), myset.end());//不让排序编译报错


	}

}

 

仿函数

一:函数对象(function object)/仿函数(functors)回顾
    函数对象 在stl中,一般都是和算法配合来使用,从而实现一些特定的功能;也就是说,这些函数对象主要用来服务于算法;
    函数名(参数列表)
    

namespace _nmsp1
{	
	class A
	{
	public:
		bool operator()(int i, int j)
		{
			return i > j; //从大到小排序
		}
	};

	void func()
	{	
		vector<int> myvector = { 50,15,80,30,46 };
		A mya;
		sort(myvector.begin(), myvector.end(), mya);

		for (auto iter = myvector.begin(); iter != myvector.end(); ++iter)
		{
			cout << *iter << endl;
		}

		return;	
	}
}

 二:标准库中定义的函数对象
    标准库中也给我们提供了很多可以现成拿来使用的函数对象,使用它们之前,要包含一个头文件 functional
    函数对象分类:
    a)算术运算类 6
    b)关系运算类 6
    c)逻辑运算类 3
    d)位运算类 3

namespace _nmsp2
{

	//三:标准库中定义的函数对象范例

	class A 
	{
	public:
		bool operator()(int i, int j)
		{
			return i > j; //从大到小排序
		}
	};

	void func()
	{
		//plus<int>(); //加圆括号是生成一个临时对象 ,就是个可调用对象;
		//plus<int> myplus;

		vector<int> myvector = { 50,15,80,30,46 };
		//A mya;  //自定义的函数对象
		//sort(myvector.begin(), myvector.end(), mya); 
		//sort(myvector.begin(), myvector.end(), greater<int>()); // greater<int>()产生临时对象,称呼为系统定义的函数对象;
		sort(myvector.begin(), myvector.end(), less<int>());


		for (auto iter = myvector.begin(); iter != myvector.end(); ++iter)
		{
			cout << *iter << endl;
		}

	}
}

适配器概念

 

namespace _nmsp1
{		
	//一:适配器基本概念:转接头
	//把一个既有的东西 进行适当的改造,比如增加点东西,或者减少点东西,就构成了一个适配器;
	//三种适配器:容器适配器,算法适配器,迭代器适配器。。。。

	//二:容器适配器(类模板):本章三节学过双端队列deque;
	//(2.1)stack:堆栈,是属于阉割版的deque;
	//(2.2)queue:队列,是属于阉割版的deque;
	//。。。。。。

	//三:算法适配器(函数适配器) :最典型的就是绑定器(binder)
	//(3.1)绑定器
	//老版本 bind1st,bind2nd;c++11,名字被修改为bind:未归类知识点第七节
	//https://en.cppreference.com/w/
	//http://www.cplusplus.com/

	class A
	{
	public:
		bool operator()(int i)
		{
			//return i > 40; //希望大于40的元素被统计
			return 40 < i;  //希望大于40的元素被统计
		}
	};

	void func()
	{	
		vector<int> myvector = { 50,15,80,30,46,80 };
		//统计某个值出现的次数
		int cishu = count(myvector.begin(), myvector.end(), 80); //算法
		cout << cishu << endl;

		//A myobja;
		//cishu = count_if(myvector.begin(), myvector.end(), myobja);
		//cout << cishu << endl;
		
		//bind(less<int>(), 40, placeholders::_1);
		                            //less<int>的operator()的第一个参数绑定为40,那这样当调用less<int>()这个可调用对象时,
		                             //第二个参数,就用这里的 placeholders::_1表示,在调用这个函数时,被传入的第一个参数所取代;
		//auto bf = bind(less<int>(), 40, placeholders::_1);
		//bf(19);

		cishu = count_if(myvector.begin(), myvector.end(), bind(less<int>(),  //临时对象
								40,placeholders::_1));
		//a)bind:函数适配器中的绑定七;
		//b)less<int>():是个函数对象(仿函数),这里是个临时对象
		//c)count_if:是个算法;
		cout << cishu << endl;
		
		return;	
	}
}
namespace _nmsp2
{
	//四:迭代器适配器
	//(4.1)reverse_iterator:二章九节讲解过:反向迭代器;
	
	//五:总结


	void func()
	{
		vector<int> iv = { 100,200,300 };
		for (vector<int>::reverse_iterator riter = iv.rbegin(); riter != iv.rend(); ++riter)
		{
			cout << *riter << endl;
		}

	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值