一、算法概述
-
算法部分主要头文件<algorithm>,<numeric>,<functional>:<algorithm>是所有STL头文件中最大的一个,常用功能范围有比较、交换、查找、遍历操作、复制、修改、反转、排序、合并;<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作;<functional>中定义了一些模板类,用以声明函数对象。
-
算法分类:操作对象,直接改变容器的内容,将原容器的内容复制一份,修改其副本,然后传回该附本。非可辨序列算法:指不直接修改其所操作的容器内容的算法(计数算法、搜索算法、比较算法);可变序列算法:指可以修改他们所操作的内容的算法(删除算法、修改算法、排序算法)
-
算法中的函数对象和谓词:
-
函数对象--》重载函数调用操作符的类,其对象常称为函数对象,即他们是行为类似函数的对象,一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。这是通过重载类的operator()来实现的。“在标准库中的很对算法都可以使用函数对象或者函数来作为自定回调行为。---实现了数据类型和算法的分离
分清楚STL算法返回的值是迭代器还是谓词(函数对象)是stl算法入门的重要点
预定义函数对象:标准模板库STL提前定义了很多预定义函数对象, #include <functional>必须包含;
-
谓词--》一元函数对象,函数参数1个;二元函数参数对象,函数参数2个。一元谓词:函数参数一个,函数返回值是bool类型,可以作为一个判断式;谓词可以是一个仿函数,也可以是一个回调函数;二元位置,函数参数2个,函数返回值是bool类型。
5.函数适配器
二、STL常用的算法
- for_each()
- for_each():用指定函数一次对指定范围内所有元素进行迭代访问,该函数不得修改序列中的元素。for_each()的第三个参数,函数对象做函数参数,函数对象做返回值。
#include <iostream> using namespace std; #include "string" #include "set" #include <vector> #include <list> #include <algorithm> #include "functional" void printV(vector<int> &v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << "\t"; } } void showElem(int &n) { cout << n << "\t"; } class CMyShow { public : CMyShow() { num = 0; } void operator()(int &n) { cout << n << "\t"; num++; } void printV() { cout << num << endl; } private : int num; }; void main41() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(5); printV(v1); cout << endl; for_each(v1.begin(), v1.end(), showElem); cout << endl; CMyShow mya; CMyShow my1=for_each(v1.begin(), v1.end(), mya); cout << endl; my1.printV();//my1和mya是两个不同的对象 mya.printV(); } void main() { main41(); cout << endl; system("pause"); }
- transform():与for_each类似,遍历所有元素,但可对容器的元素进行修改。他可以把一个容器的呀U尿素,通过op,变换到另一个容器中(同一个容器中);也可以把两个容器的元素,通过op,变换到另一个容器中。
#include <iostream> using namespace std; #include "string" #include "set" #include <vector> #include <list> #include <algorithm> #include "functional" #include "iterator" void printV(vector<int> &v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << "\t"; } } void printList(list<int> &v) { for (list<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << "\t"; } } int increase(int i) { return i + 100; } void main42() { vector<int> v1; v1.push_back(1); v1.push_back(3); v1.push_back(5); printV(v1); cout << endl; //使用回调函数 transform(v1.begin(), v1.end(), v1.begin(), increase); printV(v1); cout << endl; //使用预定义的函数对象 transform(v1.begin(), v1.end(), v1.begin(), negate<int>()); printV(v1); cout << endl; //使用函数适配器 list<int> mylist; mylist.resize(v1.size()); transform(v1.begin(), v1.end(), mylist.begin(),bind2nd(multiplies<int>(),10)); printList(mylist); cout << endl; //把运算结果直接输出到屏幕 transform(v1.begin(), v1.end(), ostream_iterator<int>(cout, "\t"), negate<int>()); } void main() { main42(); cout << endl; system("pause"); }
- for_each与transform的区别 一般情况下,for_each所使用的函数对象,参数是引用,没有返回值;tranform所使用的函数对象,参数一般不使用引用,而且还有返回值;