五、STL之常用算法
算法主要是由头文件<algorithm> <functional> <numeric>组成。
<algorithm>是所有STL头文件中最大的一个,其中常用的功能涉及到比较,交换,查找,遍历,复制,修改,反转,排序,合并等...
<numeric>体积很小,只包括在几个序列容器上进行的简单运算的模板函数.
<functional> 定义了一些模板类,用以声明函数对象。
二、常用遍历算法
/* for_each(iterator beg, iterator end, _callback); @param beg 开始迭代器 @param end 结束迭代器 @param _callback 函数回调或者函数对象 @return 函数对象 */ /* 1. for_each 调用回调函数 2. for_each 调用仿函数 3. for_each 有返回值 4. for_each 可以绑定参数进行输出 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; void myPrint(int val) { cout << val << " "; } class Print { public: void operator()(int val) { cout << val << " "; this->count++; } int count = 0; }; class Print02:public binary_function<int, int, void> { public: void operator()(int val, int start)const { cout << val + start << " "; } }; void test() { vector<int> v; for (int i = 0; i < 5; i++) { v.push_back(i); } // 1. for_each 调用回调函数 for_each(v.begin(), v.end(), myPrint); // 0 1 2 3 4 cout << endl; // 2. for_each 调用仿函数 for_each(v.begin(), v.end(), Print()); // 0 1 2 3 4 cout << endl; // 3. for_each 有返回值 Print mp = for_each(v.begin(), v.end(), Print()); // 返回值是Print类型 cout << endl; cout << "count = " << mp.count << endl; // count = 5 // 4. for_each 可以绑定参数进行输出 for_each(v.begin(), v.end(), bind2nd(Print02(), 100)); cout << endl; } int main() { test(); return EXIT_SUCCESS; }
/* transform(iterator beg1, iterator end1, iterator beg2, _callbakc); transform算法 将指定容器区间元素搬运到另一容器中 注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存 @param beg1 源容器开始迭代器 @param end1 源容器结束迭代器 @param beg2 目标容器开始迭代器 @param _cakkback 回调函数或者函数对象 @return 返回目标容器迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; class MyTransform { public: int operator()(int val) { return val; } }; void test() { vector<int> v; for (int i = 0; i < 5; i++) { v.push_back(i); } vector<int> vTarget; // 需要重新制定 vTarget的大小 vTarget.resize(v.size()); transform(v.begin(), v.end(), vTarget.begin(), MyTransform()); for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; }); cout << endl; } int main() { test(); return EXIT_SUCCESS; }
三、常用查找算法
/* find(iterator beg, iterator end, value); find算法 查找元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value 查找的元素 @return 返回查找元素的位置 */ /* 1. 查找系统存在的数据类型 2. 查找自定义数据类型, 需要重载 == */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; class Person { public: Person(string name, int age) { this->Name = name; this->Age = age; } bool operator==(const Person &p) { if ((this->Name == p.Name) && (this->Age == p.Age)) { return true; } return false; } string Name; int Age; }; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } // 1. 查找系统存在的数据类型 // 查找有没有 3 这个元素, 返回值是迭代器 vector<int>::iterator it = find(v1.begin(), v1.end(), 3); if (it != v1.end()) { cout << "找到了元素: " << *it << endl; // 找到了元素: 3 } else { cout << "没找到!" << endl; } // 2. 查找自定义数据类型 vector<Person> v2; Person p1("aaa", 10); Person p2("bbb", 20); Person p3("ccc", 30); Person p4("ddd", 40); v2.push_back(p1); v2.push_back(p2); v2.push_back(p3); v2.push_back(p4); vector<Person>::iterator Pit = find(v2.begin(), v2.end(), p3); // 直接这样是不行的,系统不知道查找逻辑,查看错误源码, 是不知道如何比较==, 所以需要重载 == if (Pit != v2.end()) { cout << "找到了, 姓名: " << Pit->Name << " 年龄: " << Pit->Age << endl; } else { cout << "没找到!" << endl; } } int main() { test(); return EXIT_SUCCESS; }
/* find_if(iterator beg, iterator end, _callback); find_if算法 条件查找 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param callback 回调函数或者谓词(返回bool类型的函数对象) @return bool 查找返回true 否则false */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; class Person { public: Person(string name, int age) { this->Name = name; this->Age = age; } string Name; int Age; }; class MyComparePerson : public binary_function<Person*, Person *, bool> { public: bool operator()(Person * p1, Person * p2) const { if(p1->Name == p2->Name && p1->Age == p2->Age) { return true; } return false; } }; void test() { vector<Person *> v1; Person p1("aaa", 10); Person p2("bbb", 20); Person p3("ccc", 30); Person p4("ddd", 40); v1.push_back(&p1); v1.push_back(&p2); v1.push_back(&p3); v1.push_back(&p4); Person *p = new Person("bbb", 20); find(v1.begin(), v1.end(), p); // 语法不会报错, 因为 p是指针, 指针可以进行比较,虽然没有意义,但是是可以的,需要的是指针指向的值 // 可以采用按照条件的方式来查找 vector<Person*>::iterator it = find_if(v1.begin(), v1.end(), bind2nd(MyComparePerson(), p)); if (it != v1.end()) { cout << "找到了: 姓名: " << (*it)->Name << " 年龄: " << (*it)->Age << endl; } else { cout << "没找到!" << endl; } } int main() { test(); return EXIT_SUCCESS; }
/* adjacent_find(iterator beg, iterator end, _callback); adjacent_find算法 查找相邻重复元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param _callback 回调函数或者谓词(返回bool类型的函数对象) @return 返回相邻元素的第一个位置的迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; class Person { public: Person(string name, int age) { this->Name = name; this->Age = age; } string Name; int Age; }; void test() { // 返回重复的并且是相邻的元素 vector<int> v; v.push_back(1); v.push_back(3); v.push_back(1); v.push_back(2); v.push_back(2); v.push_back(5); v.push_back(4); vector<int>::iterator it = adjacent_find(v.begin(), v.end()); if (it != v.end()) { cout << "找到了: " << *it << endl; // 找到了: 2 } else { cout << "没找到" << endl; } } int main() { test(); return EXIT_SUCCESS; }
/* bool binary_search(iterator beg, iterator end, value); binary_search算法 二分查找法 注意: 在无序序列中不可用 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value 查找的元素 @return bool 查找返回true 否则false */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; void test() { // 返回重复的并且是相邻的元素 vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(6); v.push_back(8); v.push_back(9); bool ret = binary_search(v.begin(), v.end(), 4); if (ret) { cout << "找到了" << endl; } else { cout << "没找到" << endl; } } int main() { test(); return EXIT_SUCCESS; }
/* count(iterator beg, iterator end, value); count算法 统计元素出现次数, 按值进行统计 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value回调函数或者谓词(返回bool类型的函数对象) @return int返回元素个数 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; void test() { vector<int> v; for (int i = 0; i < 5; i++) { v.push_back(i); } v.push_back(3); // 按值进行统计 int num = count(v.begin(), v.end(), 3); cout << "num = " << num << endl; // num = 2 } int main() { test(); return EXIT_SUCCESS; }
/* count_if(iterator beg, iterator end, _callback); count算法 统计元素出现次数 按条件进行统计 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param callback 回调函数或者谓词(返回bool类型的函数对象) @return int返回元素个数 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; class MyCompare { public: bool operator()(int val) { return val > 3; } }; void test() { vector<int> v; for (int i = 0; i < 5; i++) { v.push_back(i); } v.push_back(4); // 按条件进行统计, 统计大于3的个数 int num = count_if(v.begin(), v.end(), MyCompare()); cout << "大于3的个数: " << num << endl; // num = 2 } int main() { test(); return EXIT_SUCCESS; }
四、常用排序算法
/* merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest) merge算法 容器元素合并,并存储到另一容器中 两个容器必须是有序的 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } vector<int> v2; for (int i = 0; i < 5; i++) { v2.push_back(i + 5); } // 目标容器 vector<int> vTarget; // 扩容目标容器 vTarget.resize(v1.size() + v2.size()); merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; }); // 0 1 2 3 4 5 6 7 8 9 cout << endl; } int main() { test(); return EXIT_SUCCESS; }
/* sort(iterator beg, iterator end, _callback) sort算法 容器元素排序 注意:两个容器必须是有序的 @param beg 容器1开始迭代器 @param end 容器1结束迭代器 @param _callback 回调函数或者谓词(返回bool类型的函数对象) */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } // 从大到小排序 sort(v1.begin(), v1.end(), greater<int>()); for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 4 3 2 1 0 cout << endl; } int main() { test(); return EXIT_SUCCESS; }
/* random_shuffle(iterator beg, iterator end); sort算法 对指定范围内的元素随机调整次序, 洗牌 @param beg 容器开始迭代器 @param end 容器结束迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> #include<ctime> using namespace std; void test() { srand((unsigned int) time(NULL)); vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } random_shuffle(v1.begin(), v1.end()); for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 0 2 1 4 3 } int main() { test(); return EXIT_SUCCESS; }
/* reverse(iterator beg, iterator end) reverse算法 反转指定范围的元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<functional> using namespace std; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } v1.push_back(3); reverse(v1.begin(), v1.end()); for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 3 4 3 2 1 0 } int main() { test(); return EXIT_SUCCESS; }
五、常用拷贝和替换算法
/* copy(iterator beg, iterator end, iterator dest) copy算法 将容器内指定范围的元素拷贝到另一容器中 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param dest 目标起始迭代器 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } vector<int> v2; v2.resize(v1.size()); copy(v1.begin(), v1.end(), v2.begin()); for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; }); // 0 1 2 3 4 } int main() { test(); return EXIT_SUCCESS; }
/* replace(iterator beg, iterator end, oldvalue, newvalue); replace算法 将容器内指定范围的旧元素修改为新元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param oldvalue 旧元素 @param oldvalue 新元素 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<iterator> using namespace std; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } v1.push_back(2); replace(v1.begin(), v1.end(), 2, 300); for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 0 1 300 3 4 300 // 还可以用下面的方式输出 cout << endl; copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); // 0 1 300 3 4 300 } int main() { test(); return EXIT_SUCCESS; }
/* replace_if(iterator beg, iterator end, _callback, newvalue); replace_if算法 将容器内指定范围满足条件的元素替换为新元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param callback函数回调或者谓词(返回Bool类型的函数对象) @param oldvalue 新元素 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<iterator> using namespace std; class MyCompare { public: bool operator()(int val) { return val > 3; } }; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } v1.push_back(2); // 按条件替换, 将所有大于3的都替换成300 replace_if(v1.begin(), v1.end(), MyCompare(), 3000); for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 0 1 2 3 3000 2 // 还可以用下面的方式输出 cout << endl; copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); // 0 1 2 3 3000 2 } int main() { test(); return EXIT_SUCCESS; }
/* swap(container c1, container c2); swap算法 互换两个容器的元素 @param c1容器1 @param c2容器2 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<iterator> using namespace std; class MyCompare { public: bool operator()(int val) { return val > 3; } }; void test() { vector<int> v1; for (int i = 0; i < 5; i++) { v1.push_back(i); } v1.push_back(2); vector<int> v2; for (int i = 0; i < 8; i++) { v2.push_back(i + 10); } swap(v1, v2); // 按条件替换, 将所有大于3的都替换成300 for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 10 11 12 13 14 15 16 17 cout << endl; for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; }); // 0 1 2 3 4 2 // 还可以用下面的方式输出 cout << endl; copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " ")); //10 11 12 13 14 15 16 17 } int main() { test(); return EXIT_SUCCESS; }
六、常用算数生成算法
/* accumulate(iterator beg, iterator end, value); accumulate算法 计算容器元素累计总和 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value 起始的累加值 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<numeric> #include<iterator> using namespace std; void test() { vector<int> v; for (int i = 0; i <= 100; i++) { v.push_back(i); } // 头文件 numeric int num = accumulate(v.begin(), v.end(), 0); // 第三个参数是起始的累加值 cout << "num = " << num << endl; // num = 5050 } int main() { test(); return EXIT_SUCCESS; }
/* fill(iterator beg, iterator end, value) fill算法 向容器中添加元素 @param beg 容器开始迭代器 @param end 容器结束迭代器 @param value 填充元素 */ #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<numeric> #include<iterator> using namespace std; void test() { vector<int> v; v.resize(5); fill(v.begin(), v.end(), 500); copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); // 500 500 500 500 500 } int main() { test(); return EXIT_SUCCESS; }
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<string> #include<vector> #include<algorithm> #include<iterator> using namespace std; void test() { vector<int> v1; vector<int> v2; for (int i = 0; i < 5; i++) { v1.push_back(i); v2.push_back(i + 3); } /* 交集 set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest); set_intersection算法 求两个set集合的交集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ vector<int> vTarget; // 目标容器 vTarget.resize(min(v1.size() ,v2.size())); // 两个容器中取小的。 vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); // 3, 4 cout << endl; /* 并集 set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest); set_union算法 求两个set集合的并集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ vTarget.resize(v1.size() + v2.size()); // 两个容器中取小的。 itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); // 0 1 2 3 4 5 6 7 cout << endl; copy(vTarget.begin(), vTarget.end(), ostream_iterator<int>(cout, " ")); // 0 1 2 3 4 5 6 7 0 0 开辟空间大了 cout << endl; /* 差集 set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest); set_difference算法 求两个set集合的差集 注意:两个集合必须是有序序列 @param beg1 容器1开始迭代器 @param end1 容器1结束迭代器 @param beg2 容器2开始迭代器 @param end2 容器2结束迭代器 @param dest 目标容器开始迭代器 @return 目标容器的最后一个元素的迭代器地址 */ vTarget.resize(max(v1.size(), v2.size())); // v1 与 v2 的差集 itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " ")); // 0 1 2 cout << endl; } int main() { test(); return EXIT_SUCCESS; }