本文最后更新于:2021年2月6日 晚上
STL常用算法,for_each遍历,transfrom,find,count,sort,merge,reserve,fill以及一些集合算法等。
头文件
- 算法主要是由头文件
<algorithm>
<functional>
<numeric>
组成。
<algorithm>
是所有STL头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等等
<numeric>
体积很小,只包括几个在序列上面进行简单数学运算的模板函数
<functional>
定义了一些模板类,用以声明函数对象。
常用遍历算法
for_each
for_each(iterator beg, iterator end, _func);
- beg 开始迭代器
- end 结束迭代器
- _func 函数或者函数对象,自定义方式。
- 通过调用
_func
来实现遍历容器元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class MyPrint { public: void operator()(int a) { cout << a << " "; } };
void test1() {
vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i);
for_each(v.begin(),v.end(),MyPrint()); }
|
transform(iterator beg1, iterator end1, iterator beg2, _func);
- beg1 源容器开始迭代器
- end1 源容器结束迭代器
- beg2 目的容器开始迭代器
- _func 函数或者函数对象,自定义方式。
- 搬运容器到另一个容器中,中间可通过_func来处理数据。
- 搬运到新的容器一定要先开辟空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class MyPrint { public: void operator()(int a) { cout << a << " "; } };
class MyTransform { public: int operator()(int a) { return a * 10; } };
void test2() {
vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i);
list<int> l; l.resize(v.size());
transform(v.begin(),v.end(),l.begin(), MyTransform());
for_each(l.begin(), l.end(), MyPrint());
}
|
常用查找算法
find
find(iterator beg, iterator end, value);
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
- 按值查找元素,找到返回指定位置迭代器,找不到返回end()结束迭代器位置
- find底层使用了
==
运算符,所以自定义数据类型应当重载这个符号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| class Cat { public: Cat(string name, int age) { m_name = name; m_age = age; }
bool operator==(const Cat& other){ if (m_name == other.m_name && m_age == other.m_age) return true; else return false; }
string m_name; int m_age; };
void test3() {
vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i);
vector<int>::iterator it = find(v.begin(),v.end(),5); if (it == v.end()) cout << "没有找到" << endl; else cout << "已经找到:" << *it << endl;
Cat c1("Tom",3); Cat c2("Jerry",4); Cat c3("Bob",3);
vector<Cat> vc;
vc.push_back(c1); vc.push_back(c2); vc.push_back(c3);
Cat c("Tom", 3);
vector<Cat>::iterator itc = find(vc.begin(), vc.end(), c); if (itc == vc.end()) cout << "没有找到" << endl; else cout << "已经找到:" << itc->m_name << endl;
}
|
find_if
find_if(iterator beg, iterator end, _Pred);
- beg 开始迭代器
- end 结束迭代器
- _Pred 函数或者谓词(返回bool类型的仿函数)
- 按条件查找元素,找到返回指定位置迭代器,找不到返回end()结束迭代器位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class Greaterive { public: bool operator()(int a) { return a > 5; } };
class CatGreater3 { public: bool operator()(const Cat& c) { if (c.m_age > 3) return true; else return false; } };
void test4() {
vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i);
vector<int>::iterator it = find_if(v.begin(), v.end(), Greaterive()); if (it == v.end()) cout << "没有找到大于5" << endl; else cout << "已经找到大于5:" << *it << endl;
Cat c1("Tom", 3); Cat c2("Jerry", 4); Cat c3("Bob", 3);
vector<Cat> vc;
vc.push_back(c1); vc.push_back(c2); vc.push_back(c3);
Cat c("Tom", 3);
vector<Cat>::iterator itc = find_if(vc.begin(), vc.end(), CatGreater3()); if (itc == vc.end()) cout << "没有找到3岁以上的猫" << endl; else cout << "已经找到3岁以上的猫:" << itc->m_name << endl;
}
|
adjacent_find 查找相邻重复元素
adjacent_find(iterator beg, iterator end);
- 查找相邻重复元素,返回相邻元素的第一个位置的迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void test5() {
vector<int> v; v.push_back(2); v.push_back(1); v.push_back(3); v.push_back(2); v.push_back(4); v.push_back(4);
vector<int>::iterator it = adjacent_find(v.begin(),v.end());
if (it == v.end()) cout << "没有找到相邻且重复的元素" << endl; else cout << "找到了相邻且重复的元素" << *it << endl;
}
|
binary_search 二分查找
bool binary_search(iterator beg, iterator end, value);
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
- 使用二分查找查找指定元素
- 必须对有序序列进行查找,否则结果不可知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void test6() {
vector<int> v; int num1 = 1; int num2 = 20; for (int i = 0; i < 10; i++) { v.push_back(num1++); v.push_back(num2--); }
for_each(v.begin(),v.end(),MyPrint());
bool flag = binary_search(v.begin(),v.end(),7);
if (flag) cout << "找到了" << endl; else cout << "未找到" << endl;
sort(v.begin(), v.end());
flag = binary_search(v.begin(), v.end(), 7);
if (flag) cout << "找到了" << endl; else cout << "未找到" << endl;
}
|
输出结果:
count 统计
int count(iterator beg, iterator end, value);
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
- 按照值进行统计,返回出现的次数。
- 对于自定义数据类型应当
重载==操作符
。
count_if
count_if(iterator beg, iterator end, _Pred);
- beg 开始迭代器
- end 结束迭代器
- _Pred 谓词,自定义
- 按照自定义的条件来统计元素个数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Greater4 {
public: bool operator()(int a) { return a > 4; }
};
void test7() {
vector<int> v; v.push_back(2); v.push_back(1); v.push_back(3); v.push_back(2); v.push_back(4); v.push_back(4); v.push_back(7); v.push_back(9);
int num = count(v.begin(), v.end(), 4); cout << "4的个数为:" << num << endl;
num = count_if(v.begin(),v.end(),Greater4()); cout << "大于4的个数为:" << num << endl;
}
|
常用排序算法
sort 排序
sort(iterator beg, iterator end, _Pred);
- beg 开始迭代器
- end 结束迭代器
- _Pred 谓词,自定义,或者使用STL中已有的谓词
- 对容器内元素进行排序,默认是升序排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void test8() { vector<int> v;
v.push_back(5); v.push_back(3); v.push_back(1); v.push_back(6); v.push_back(4); v.push_back(2);
for_each(v.begin(), v.end(), MyPrint()); cout << endl;
sort(v.begin(), v.end());
for_each(v.begin(), v.end(), MyPrint()); cout << endl;
sort(v.begin(),v.end(),greater<int>());
for_each(v.begin(), v.end(), MyPrint()); cout << endl;
}
|
random_shuffle 洗牌
random_shuffle(iterator beg, iterator end);
- 指定范围内的元素随机调整次序.
- 可设置随机数种子,使得每次结果均不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void test9() {
srand((unsigned int)time(NULL));
vector<int> v; for (int i = 0; i < 10; i++) v.push_back(i);
random_shuffle(v.begin(),v.end());
for_each(v.begin(), v.end(), MyPrint());
}
|
merge 合并
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest, _Pred );
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
- _Pred 谓词,默认由小到大排序,可省略
- 将两个容器的元素合并,并存储到另一个容器之中。
- 两个容器必须是有序的,且顺序相同,并且和merge中的顺序相同,最终排序结果仍然有序。否则就会报错。
- 目标容器必须先预先分配空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void test10() {
vector<int> v1; vector<int> v2;
for (int i = 0; i < 10; i++) { v1.push_back(10-i); v2.push_back(10-i); }
vector<int> v3; v3.resize(v1.size()+v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin(),greater<int>());
for_each(v3.begin(),v3.end(),MyPrint()); }
|
reserve 反转
reverse(iterator beg, iterator end);
- 将容器内元素进行反转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void test11() {
vector<int> v1;
for (int i = 0; i < 10; i++) { v1.push_back(10 - i); }
reverse(v1.begin(),v1.end());
for_each(v1.begin(), v1.end(), MyPrint());
}
|
常用拷贝和替换算法
copy
copy(iterator beg, iterator end, iterator dest);
- beg 开始迭代器
- end 结束迭代器
- dest 目标容器开始迭代器
- 容器内指定范围的元素拷贝到另一容器中,当然用这些容器提供的自带的构造方法也可以完成。
- 拷贝前记得给目标容器开辟空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class MyPrint { public: void operator()(int val) { cout << val << " "; } };
void test1() {
list<int> l; for (int i = 0; i < 10; i++) l.push_back(i);
list<int> l2; l2.resize(l.size());
copy(l.begin(), l.end(), l2.begin());
for_each(l2.begin(),l2.end(),MyPrint()); }
|
replace
replace(iterator beg, iterator end, oldvalue, newvalue);
- beg 开始迭代器
- end 结束迭代器
- oldvalue 旧元素
- newvalue 新元素
- 将容器内指定范围的旧元素修改为新元素。
replace_if
replace_if(iterator beg, iterator end, _pred, newvalue);
- beg 开始迭代器
- end 结束迭代器
- _pred 谓词,自定义条件
- newvalue 新元素
- 将区间内满足条件的元素,替换成指定元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Greater3 { public: bool operator()(int val) { return val > 3; } };
void test2() {
vector<int> v;
v.push_back(2); v.push_back(3); v.push_back(5); v.push_back(1); v.push_back(6); v.push_back(3); v.push_back(7); v.push_back(2);
for_each(v.begin(), v.end(), MyPrint()); cout << endl;
replace(v.begin(),v.end(),2,-20);
for_each(v.begin(), v.end(), MyPrint()); cout << endl;
replace_if(v.begin(),v.end(), Greater3(),25);
for_each(v.begin(), v.end(), MyPrint()); cout << endl; }
|
swap
swap(container c1, container c2);
- 互换两个容器的元素。其实一些容器本身也提供了这样的方法。
常用算术生成算法
- 算术生成算法属于小型算法,使用时包含的头文件为
#include <numeric>
accumulate —— 元素累加
accumulate(iterator beg, iterator end, value);
- beg 开始迭代器
- end 结束迭代器
- value 表示累加的起始值
- 计算区间内 容器元素累计总和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <numeric>//注意头文件
void test3() {
vector<int>v; for (int i = 1; i <= 100; i++) { v.push_back(i); }
int total1 = accumulate(v.begin(),v.end(),0); int total2 = accumulate(v.begin(),v.end(),1000);
cout << total1 << endl; cout << total2 << endl; }
|
fill —— 填充
fill(iterator beg, iterator end, value);
- beg 开始迭代器
- end 结束迭代器
- value 填充的值
- 向容器中填充指定的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13
| void test4() {
vector<int> v;
v.resize(10);
fill(v.begin(), v.end(), 99);
for_each(v.begin(),v.end(),MyPrint());
}
|
常用集合算法
set_intersection 求交集
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
- 求两个容器的交集。两个集合必须是有序序列。
- 函数返回值是最后一个元素的迭代器地址的下一个位置。
- 记得给目标容器开辟空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void test6() {
vector<int> v1; vector<int> v2;
for (int i = 0; i < 10; i++) { v1.push_back(i); v2.push_back(i+8); }
vector<int> v3; v3.resize(min(v1.size(),v2.size()));
vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(),v2.begin(),v2.end(),v3.begin());
for_each(v3.begin(), itEnd,MyPrint()); cout << endl;
for_each(v3.begin(), v3.end(), MyPrint());
}
|
set_union 求并集
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
- 求两个容器的并集。两个集合必须是有序序列。
- 函数返回值是最后一个元素的迭代器地址的下一个位置。
- 记得给目标容器开辟空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void test7() {
vector<int> v1; vector<int> v2;
for (int i = 0; i < 10; i++) { v1.push_back(i); v2.push_back(i + 8); }
vector<int> v3; v3.resize(v1.size()+v2.size());
vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
for_each(v3.begin(),itEnd,MyPrint());
}
|
set_difference
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
- 求两个容器的差集。两个集合必须是有序序列。
- 函数返回值是最后一个元素的迭代器地址的下一个位置。
- 记得给目标容器开辟空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void test8() {
vector<int> v1; vector<int> v2;
for (int i = 0; i < 10; i++) { v1.push_back(i); v2.push_back(i + 8); }
vector<int> v3; v3.resize(max(v1.size(), v2.size()));
vector<int>::iterator itEnd = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
cout << "v1 对于 v2 的差集" << endl; for_each(v3.begin(), itEnd, MyPrint()); cout << endl;
itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v3.begin());
cout << "v2 对于 v1 的差集" << endl; for_each(v3.begin(), itEnd, MyPrint()); cout << endl;
}
|
运行结果:
1 2 3 4
| v1 对于 v2 的差集 0 1 2 3 4 5 6 7 v2 对于 v1 的差集 10 11 12 13 14 15 16 17
|