天天看點

8-6 算法 8-7 仿函數 8-8 擴充卡算法

算法

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中,一般都是和算法配合來使用,進而實作一些特定的功能;也就是說,這些函數對象主要用來服務于算法;

    函數名(參數清單)

8-6 算法 8-7 仿函數 8-8 擴充卡算法
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

8-6 算法 8-7 仿函數 8-8 擴充卡算法
8-6 算法 8-7 仿函數 8-8 擴充卡算法
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;
		}

	}
}
           

擴充卡概念

8-6 算法 8-7 仿函數 8-8 擴充卡算法
8-6 算法 8-7 仿函數 8-8 擴充卡算法
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;
		}

	}
}