STL之常用算法(C++)持续更新
2019-03-18 18:53
120 查看
STL之常用算法
- 概述
- 0. 头文件
- 1.fill、fill_n、generate、generate_n
- 2. equal、mismatch、lexicographical_compare
- 3. remove、remove_if、remove_copy、remove_copy_if
- 4. replace、replace_if、replace_copy、replace_copy_if
- 5. 数学算法
- 6. 基本查找和排序算法: find、find_if、sort、binary_search
- 7. swap、iter_swap、swap_ranges
- 8. copy、copy_backward、merge、unique、reverse
- 9. inplace_merge、unique_copy、reverse_copy
- 10. 集合操作:includes、set_difference、set_intersection、set_symmetric_difference、set_union
- 11. lower_bound、upper_bound、equal_range
- 12. 堆排序:make_heap、sort_heap、push_heap、pop_heap
- 13. min、max
- 14. 其他算法
概述
- STL将算法和容器分开,使得更容易加入新算法。这样实现的STL能更加有效,避免了虚函数调用的相关开销。
- STL算法不依赖于所操作容器的实现细节。只要容器(或数组)的迭代器符合算法要求,STL算法即可像STL容器一样处理任何C语言式、基于指针的数组(以及用户自定义的数据结构)。
- 不必修改容器就能方便地将算法加进STL中。
0. 头文件
#include<algorithm>
1.fill、fill_n、generate、generate_n
- 函数fill和fill_n将容器中一定范围的元素设置为特定值。
- 函数generate和generate_n用产生器函数生成容器中一定范围的元素值。产生器函数不取参数,并返回可以放在容器元素中的值。
vector<char>v1(10); //输出v1:0 0 0 0 0 0 0 0 0 0 //将字符‘5’放在v1从begin到end(不包括end)的每个元素中 fill(v1.begin(), v1.end(), '5'); //输出v1:5 5 5 5 5 5 5 5 5 5 //将字符‘A’放在v1的前5个元素中 fill_n(v1.begin(), 5, 'A'); //输出v1:A A A A A 5 5 5 5 5 //将调用产生器函数nextLetter得到的结果放在v1的begin到end(不包括end)的每个元素中 generate(v1.begin, v1.end(), nextLetter); //输出v1:A B C D E F G H I J //将调用产生器函数nextLetter得到的结果放在v1的前5个元素中 generate_n(v1.begin(), 5, nextLetter); //输出v1:K L M N O F G H I J char nextLetter() { static char letter = 'A'; return letter++; }
2. equal、mismatch、lexicographical_compare
- 函数equal比较两个数值序列的相等性,每个序列不一定包含相同的元素个数,如果两个序列的元素个数不同,则equal返回false。函数operator==进行元素的比较。
- 函数equal有一种形式:取一个二元判定函数作为第4个参数,二元判定函数接受两个要比较的元素并返回一个bool值,表示元素是否相同。这可以在存放数值指针而不是存放实际数值的序列中有用,因为可以定义指针所指项目的比较,而不是比较指针内容(即指针中存放的地址)。
- 函数mismatch比较两个数值序列,返回一个pair迭代器对,表示每个序列中不匹配元素的地址。如果所有元素匹配,则pair中的两个迭代器等于每个序列的end()。同函数equal一样,mismatch也有另一种形式:取一个二元判定函数作为第4个参数。
- 函数lexicographical比较两个字符数组的内容。如果第一个序列中的元素小于第二个序列中的元素,则返回true,否则返回false。这个函数通常可以按词法排序序列,这个序列通常包含字符串。
vector<int>v1 = { 1,2,3,4,5 }; vector<int>v2 = { 1,2,3,4,5 }; vector<int>v3 = { 1,2,3,5,4 }; // bool result = equal(v1.begin(), v1.end(), v2.begin()); //返回true bool result = equal(v1.begin(), v1.end(), v3.begin()); //返回false // pair<vector<int>::iterator, vector<int>::iterator> p1; p1 = mismatch(v1.begin(), v1.end(), v3.begin()); //返回数值对 cout << *p1.first << " " << *p1.second; //输出4 5 (*即取地址中存放的元素的值) cout << (p1.first - v1.begin()); //输出 3 (取迭代器的差值得到实际不同的第一个元素的下标) // char c1[10] = "HELLO"; char c2[10] = “BYE BYE”; result = lexicographical_compare(c1, c1 + 10, c2, c2 + 10);//返回false
3. remove、remove_if、remove_copy、remove_copy_if
- remove:在一个序列中删除指定值。 不修改vector中的元素个数,也不破坏删除的元素,而是将所有未删除元素放在vector开头。函数返回vector中最后一个未删除元素后面一位的迭代器。从这个迭代器位置到vector末尾的元素数值为未定义(本例中为0)
- remove_copy:把一个序列中删除指定值后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
- remove_if:在一个序列中删除满足指定函数的元素。 不修改vector中的元素个数,也不破坏删除的元素,而是将所有未删除元素放在vector开头。函数返回vector中最后一个未删除元素后面一位的迭代器。从这个迭代器位置到vector末尾的元素数值为未定义(本例中为0)
- remove_copy_if:在一个序列中删除满足指定函数的元素后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
vector<int>v1 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v2 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v3 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v4 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v0(10, 5); vector<int>v00(10, 5); //删除v1中从头到尾范围内所有数值为10的元素。 //v1变成 2 4 16 6 14 8 12 0 0 0,iter指向第一个0的迭代器 vector<int>::iterator iter; iter=remove(v1.begin(), v1.end(), 10); //复制v2中从头到尾的所有数值不为10的元素,放在v0中,从v0的begin开始。 修改的对象是第3个参数。 //v0变成 2 4 16 6 14 8 12 5 5 5 remove_copy(v2.begin(), v2.end(), v0.begin(), 10); //删除v3中从头到尾的,第三个参数(用户自定义的一元判定函数greater9)返回为true的所有元素 //v3变成 2 4 6 8 0 0 0 0 0 0,iter指向第一个0的迭代器 vector<int>::iterator iter; iter=remove_if(v3.begin(), v3.end(), greater9); //复制v4中从头到尾的,第三个参数(用户自定义的一元判定函数greater9)返回为true的所有 元素,放在v00中,从v00的begin开始。修改的对象是第3个参数。 //v00变成 2 4 6 8 5 5 5 5 5 5 remove_copy_if(v4.begin(), v4.end(), v00.begin(), greater9);
4. replace、replace_if、replace_copy、replace_copy_if
- replace:在一个序列中将某个值替换成指定值。
- replace_copy:把一个序列中将某个值替换成指定值后,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个元素后面一位的迭代器。
- replace_if:在一个序列中将所有满足指定函数的值替换成指定值。
- replace_copy_if:把一个序列中将所有满足指定函数的值替换成指定值,把该序列复制到指定序列指定位置。 函数返回复制到vector的最后一个 20000 元素后面一位的迭代器。
vector<int>v1 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v2 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v3 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v4 = { 10,2,10,4,16,6,14,8,12,10 }; vector<int>v0(10, 5); vector<int>v00(10, 5); //替换v1中从头到尾范围内所有数值为10的元素为100。 //v1变成 100 2 100 4 16 6 14 8 12 100 replace(v1.begin(), v1.end(), 10, 100); //复制v2中从头到尾的所有元素,将数值10的元素替换成新值100,放在v0中,从v0的begin开始。 修改的对象是第3个参数。 //v0变成 100 2 100 4 16 6 14 8 12 100 replace_copy(v2.begin(), v2.end(), v0.begin(), 10, 100); //替换v3中从头到尾的,第3个参数(用户自定义的一元判定函数greater9)返回为true的所有元素, 即每个满足greater9的元素都替换成100 //v3变成 100 2 100 4 100 6 100 8 100 100 replace_if(v3.begin(), v3.end(), greater9, 100); //复制v4中从头到尾的,第3个参数(用户自定义的一元判定函数greater9)返回为true的所有元素 (即每个满足greater9的元素都替换成100),然后放在v0中,从v0的begin开始。修改的对象是第3 个参数。 //v00变成 100 2 100 4 100 6 100 8 100 100 replace_copy_if(v4.begin(), v4.end(), v00.begin(), greater9);
5. 数学算法
- random_shuffle:对选定范围的元素随机排序。
- count:对选定范围的元素,为某个数值的元素的个数。
- count_if:对选定范围的元素,符合条件的元素的个数。
- min_element:对选定范围的元素,找到最小元素的位置的输入迭代器
- max_element:对选定范围的元素,找到最大元素的位置的输入迭代器
- accumulate:对指定范围的所有元素进行特定函数的累加计算。
- for_each:对指定范围的所有元素进行特定函数操作。
- transform:对指定范围的所有元素替换成进行特定函数的操作后的元素值。
vector<int>v1 ; //随机排序v1中从头到尾的元素 random_shuffle(v1.begin(), v1.end()); //计算v1从头到尾元素数值为8的元素个数 int result = count(v1.begin(), v2.end(), 8); //计算v1从头到尾元素的元素中,判定函数greater9返回为true的元素个数 int result = count_if(v1.begin(), v1.end(), greater9); //计算v1从头到尾元素的元素中的最小元素,返回最小元素位置的迭代器,若范围为空则 返回迭代器本身 int min = *min_element(v1.begin(), v1.end()); //计算v1从头到尾元素的元素中的最大元素,返回最大元素位置的迭代器,若范围为空则 返回迭代器本身 int max = *max_element(v1.begin(), v1.end()); //计算元素数值和 int sum = accumulate(v1.begin(), v1.end(), 0); //计算元素数值的平方和 int sum = accumulate(v1.begin(), v1.end(), sumOfSquare); int sumOfSquare(int accumulator, int currentValue) { return accumulator + currentValue * currentValue; } //对v1从头到尾的每个元素采用常用函数(本例为求平方) for_each(v1.begin(), v1.end(), outputSquare); void outputSquare(int value) { cout << value * value << " "; } //对v1从头到尾的每个元素采用常用函数(本例为求立方)进行值的替换,第3个参数制定变换结果 值的存放位置,注意第3个参数可以等于第一个参数 transform(v1.begin(), v1.end(), v1.begin(), calculateCube); int calculateCube(int value) { return value * value * value; }
6. 基本查找和排序算法: find、find_if、sort、binary_search
- find:在指定序列指定范围的元素中寻找指定数值。返回第1个符合的位置迭代器。
- find_if:在指定序列指定范围的元素中寻找符合指定函数的元素。返回第1个符合的位置迭代器。
- sort:对指定序列的指定范围内的元素进行排序。
- binary_search:判断在指定序列指定范围内是否出现指定值。
vector<int>::iterator loaction; //寻找v1中从头到尾所有元素中,数值为100的元素, //函数返回一个输入迭代器,表示第1个包含该值的元素位置或end() loaction = find(v1.begin(), v1.end(), 100); //寻找v1中从头到尾所有元素中,一元判定函数greater9返回为true的第1个值。 //函数返回一个输入迭代器,表示第1个greater9返回true的值的元素位置或end() loaction = find_if(v1.begin(), v1.end(), greater9); //在给定范围内的元素按升序排列 //函数sort要求随机访问迭代器 sort(v1.begin(), v1.end()); //确定数值13是否在给定范围内的元素的数值之中 bool result=binary_search(v1.begin(), v1.end(), 13);
7. swap、iter_swap、swap_ranges
- swap:交换指定位置的元素。
- iter_swap:交换迭代器所指的元素的值。
- swap_ranges:交换两个指定序列的所有元素。
//交换数组第1个元素和第2个元素 //a[]变成 2 1 3 4 5 int a[] = { 1,2,3,4,5 }; swap(a[0], a[1]); //函数取两个正向迭代器参数(这里是数组元素的指针),交换迭代器所指元素的值 //a[]变成 2 1 3 4 5 int a[] = { 1,2,3,4,5 }; iter_swap(&a[0], &a[1]); //交换a开始到a+5(不包括)的元素与从a+5开始的元素 //a[]变成 6 7 8 9 10 1 2 3 4 5 int a[] = { 1,2,3,4,5,6,7,8,9,10 }; swap_ranges(a, a + 5, a + 5);
8. copy、copy_backward、merge、unique、reverse
- copy:将某个序列指定范围的元素,复制到指定序列v1。返回是复制到指定序列的最后一个元素位置的迭代器,为v1.end()。
- copy_backward:与copy基本相似。返回的是复制到某序列的最后一个元素位置的迭代器,为v1.begin()。
- merge:组合两个序列,并复制到一个指定序列中。
- unique:去除重复值,只保留一个副本。
- reverse:对指定序列指定范围的所有元素进行调转。
vector<int>v1 = { 1,2,3,9 }; vector<int>v2 = { 4,7,8,8,10 }; vector<int>v3 = { 1,3,5,1,3,5 }; vector<int>result1,result3; vector<int>result2(10); //将v1中从头到尾所有元素复制到result1,从result1.begin()开始从前往后开始复制 //函数返回result.begin()(若是copy函数返回result.end()) //result1变成 1 2 3 9 copy(v1.begin(), v1.end(), result1.begin()); //将v1中从头到尾所有元素复制到result1,从result1.end()开始从后往前开始复制 //函数返回result.begin()(若是copy函数返回result.end()) //result1变成 1 2 3 9 copy_backward(v1.begin(), v1.end(), result1.end()); //组合v1,v2序列,复制所有元素到result2的开头处。 //如果在merge操作之前未对结果序列分配足够的长度,可以用back_inserter //back_inserter调用容器默认的push_back函数,在末尾插入一个元素 //result2变成 1 2 3 4 7 8 8 9 10 merge(v1.begin(), v1.end(), v2.begin(), v2.end(), result2.begin()); 或 merge(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(result3)); //去除重复值,序列中每个值只有1个副本,不改变元素个数,去除的元素放在最后,设为未定义 //v2变成 4 7 8 10 0 unique(v2.begin(), v2.end()); //将给定范围的所有元素调转顺序 //v1变成 9 3 2 1 reverse(v1.begin(), v1.end()); vector<int>::iterator loaction; loaction=find(v1.begin(),v1.end(),100); loaction=find_if(v1.begin(),v1.end(),greater9);
9. inplace_merge、unique_copy、reverse_copy
- inplace_merge:合并同一容器中的两个已排序的元素序列。
- unique_copy:复制某个序列某个范围去重后的所有元素,放入指定序列指定位置后。
- reverse_copy:复制某个序列某个范围调转后的所有元素,放入指定序列指定位置后。
vector<int>v2 = { 4,7,8,8,10 }; vector<int>v3 = { 1,3,5,1,3,5 }; vector<int>result3; //合并同一容器中的两个排序元素序列 //v3变成 1 1 3 3 5 5 inplace_merge(v3.begin(),v3.begin()+3,v3.end()); //复制v2从头到尾的去重后的所有元素,放入result3中 //操作之前若未对结果序列分配足够的长度,用back_inserter //result3变成 4 7 8 10 unique_copy(v2.begin(), v2.end(), result3.begin());、 或 unique_copy(v2.begin(), v2.end(), back_inserter(result3)); //复制v2从头到尾所有元素,调转顺序,放入result3中 //操作之前未对结果序列分配足够的长度,用back_inserter //result3变成 10 8 8 7 4 reverse_copy(v2.begin(), v2.end(), result3.begin()); 或 reverse_copy(v2.begin(), v2.end(), back_inserter(result3));
10. 集合操作:includes、set_difference、set_intersection、set_symmetric_difference、set_union
- includes:确认第2个集合的每个元素是否都在第1个集合中。
- set_difference:求差集。确定在第1个集合中而不在第2个集合中的元素。
- set_intersection:求交集。确定在第1个集合中也在第2个集合中的元素。
- set_symmetric_difference:求相互的差集。在1不在2元素 + 在2不在1元素。
- set_union:求并集。在1出现过的元素和在2出现过的元素,去重之后复制
int a1[] = { 1,2,3,4,5,6,7,8,9,10 }; int a2[] = { 1,2,3,4,5}; int a3[] = { 1,2,6,7,8}; int b1[10], b2[10], b3[10], b4[10]; //确认第2个集合的每个元素是否都在第1个集合中,返回bool值 bool result = includes(a1, a1 + 10, a2, a2 + 5); //求差集。确定在第1个集合中而不在第2个集合中的元素。 //返回一个输出迭代器,放在最后复制值的后面 //b1变成 6 7 8 9 10 int *ptr1 = set_difference(a1, a1 + 10, a2, a2 + 5, b1); //求交集。确定在第1个集合中也在第2个集合中的元素。 //返回一个输出迭代器,放在最后复制值的后面 //b2变成 1 2 3 4 5 int *ptr2 = set_intersection(a1, a1 + 10, a2, a2 + 5, b2); //求相互的差集。在1不在2元素 + 在2不在1元素 //返回一个输出迭代器,放在最后复制值的后面 //b3变成 3 4 5 6 7 8 int *ptr3 = set_symmetric_difference(a2, a2 + 5, a3, a3 + 5, b3); //求并集。在1出现过的元素和在2出现过的元素,去重之后复制 //返回一个输出迭代器,放在最后复制值的后面 //b4变成 1 2 3 4 5 6 7 8 int *ptr4 = set_union(a2, a2 + 5, a3, a3 + 5, b4);
11. lower_bound、upper_bound、equal_range
- lower_bound:找到在某序列某范围内插入指定值后,仍能保持升序的第1个位置。返回该位置迭代器。
- upper_bound:找到在某序列某范围内插入指定值后,仍能保持升序的最后1个位置。返回该位置迭代器。
- equal_range:找到在某序列某范围内插入指定值后,仍能保持升序的第1个位置和最后1个位置。返回该位置迭代器对。
vector<int>v1 = { 2,2,4,4,6,6,6,8 }; //确定在v1给定范围内插入6后,仍能保持升序的第1个位置 //函数返回一个正向迭代器,指向插入的位 vector<int>::iterator lower; lower=lower_bound(v1.begin(), v1.end(), 6); cout << lower - v1.begin(); //输出4 //确定在v1给定范围内插入6后,仍能保持升序的最后1个位置 //函数返回一个正向迭代器,指向插入的位置 vector<int>::iterator upper; upper = upper_bound(v1.begin(), v1.end(), 6); cout << upper - v1.begin(); //输出7 //返回一个正向迭代器对pair(first,second),包含lower_bound和upper_bound操作的组合结果 pair<vector<int>::iterator, vector<int>::iterator> eq; eq = equal_range(v1.begin(), v1.end(), 6); cout << eq.first - v1.begin() << " " << eq.second - v1.begin(); //输出 4 7
12. 堆排序:make_heap、sort_heap、push_heap、pop_heap
- make_heap:对指定序列(数组、vector、deque)建造最大堆。
- sort_heap:升序排列。
- push_heap:在堆中增加新值(保持最大堆)。
- pop_heap:去掉堆顶元素(保持最大堆)。
参数应为随机访问迭代器,因此只适用于数组、vector、deque
vector<int>nums = { 3,100,52,77,22,31,1,98,13,40 }; vector<int>v; //建造最大堆 //nums变成 100 98 52 77 40 31 1 3 13 22 make_heap(nums.begin(), nums.end()); //升序排序 //nums变成 1 3 13 22 31 40 52 77 98 100 sort_heap(nums.begin(), nums.end()); //在堆中增加新值 for (int i = 0; i < nums.size(); i++) { v.push_back(nums[i]); push_heap(v.begin(), v.end()); } vector<int>nums = { 3,100,52,77,22,31,1,98,13,40 }; //新增3,输出v:3 //新增100,输出v:100 3 //新增52,输出v:100 3 52 //新增77,输出v:100 77 52 3 //新增22,输出v:100 77 52 3 22 //新增31,输出v:100 77 52 3 22 31 //新增1,输出v:100 77 52 3 22 31 1 //新增98,输出v:100 98 52 77 22 31 1 3 //新增13,输出v:100 98 52 77 22 31 1 3 13 //新增40,输出v:100 98 52 77 40 31 1 3 13 22 //在堆中删除堆顶元素,操作后是按升序排列的。 for (int i = 0; i < v.size(); i++) { pop_heap(v.begin(), v.end()-i); } //删除栈顶100,输出v:98 77 52 22 40 31 1 3 13 100 //删除栈顶98,输出v:77 40 52 22 13 31 1 3 98 100 //删除栈顶77,输出v:52 40 31 22 13 3 1 77 98 100 //删除栈顶52,输出v:40 22 31 1 13 3 52 77 98 100 //删除栈顶40,输出v:31 22 3 1 13 40 52 77 98 100 //删除栈顶31,输出v:22 13 3 1 31 40 52 77 98 100 //删除栈顶22,输出v:13 1 3 22 31 40 52 77 98 100 //删除栈顶13,输出v:3 1 13 22 31 40 52 77 98 100 //删除栈顶3 ,输出v:1 3 13 22 31 40 52 77 98 100 //删除栈顶1 ,输出v:1 3 13 22 31 40 52 77 98 100
13. min、max
- min:对两个输入参数比较大小,输出较小的
- max:对两个输入参数比较大小,输出较大的
cout<<min(12,7); //输出7
14. 其他算法
相关文章推荐
- STL中常用的一些算法函数[持续更新]
- STL中常用的一些算法函数[持续更新
- 【算法专题】工欲善其事必先利其器—— C++ STL中vector(向量/不定长数组)的常用方法总结
- 编程常用算法 --- C/C++ 语言实现(不定期更新)
- C++常用小技巧个人总结(持续更新)
- C++ STL 常用算法
- 【C++研发面试笔记】21. 常用算法-STL中常用算法函数
- C++中常用代码在C#中的对应(持续更新)
- Cpp--C++中排序常用(菜鸟上路,持续更新)
- C++的一些常用知识(持续更新)
- C++学习STL之顺序容器(持续更新)
- C++ STL 常用算法
- c++ STL常用算法使用方法
- C++成长之路(11)——常用头文件及相应函数【持续更新ing】
- c++面试必须熟练掌握的算法(持续更新)
- C++ STL常用算法与容器
- C++技巧之STL(持续更新)
- C++ STL应用(持续更新……)
- C++中STL常用算法概要
- 【算法基础个人常用总结】<-------持续更新------->