STL常用算法学习笔记
方便查阅、b站黑马程序员的c++
STL常用算法
C++STL中的内置算法主要在头文件<algorithm>、<functional>、<numeric>中
<algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等,也是最常用的一个头文件<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数<functional>定义了一些模板类,用以声明函数对象
常用遍历算法
下面的函数原型是视频里面的,建议去cplusplus查看,或自己跳转
for_each
功能: 实现遍历容器
函数原型:
for_each(iterator beg, iterator end, _func);
transform
功能: 搬运容器到另一个容器中
函数原型:
transform(iterator beg1, iterator end1, iterator beg2, _func);
常用查找算法
find
功能: 查找指定元素,找到返回元素迭代器,否者返回end迭代器
函数原型:
find(iterator beg, iterator end, value);
find_if
功能: 按条件查找元素,找到返回元素迭代器,否者返回end迭代器
函数原型:
find_if(iterator beg, iterator end, _Pred);
adjacent_find
功能: 查找相邻且重复的元素,返回相邻元素的第一个位置的迭代器
函数原型:
adjacent_find(iterator beg, iterator end);
binary_find
功能: 查找指定的元素,找到返回true,否则返回false
函数原型:
bool binary_search(iterator beg, iterator end, value);
count
功能: 统计元素个数
函数原型:
count(iterator beg, iterator end, value);
count_if
功能: 按条件统计元素个数
函数原型:
count_if(iteraotr beg, iterator end, _Pred);
常用排序算法
sort
功能: 对容器内元素进行排序
函数原型:
sort(iterator beg, iterator end, _Pred);
random_shuffle
功能: 洗牌 指定范围内的元素调整次序
函数原型:
random_shuffle(iterator beg, iterator end);
merge
功能: 两个容器元素合并,并存储到另一个容器中,合并后是有序的
注意: 两个容器必须是有序的
函数原型:
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator target_beg);
reverse
功能: 将容器内元素进行反转
函数原型:
reverse(iterator beg, iterator end);
常见的拷贝函数
copy
功能: 容器内指定范围的元素拷贝到另一容器中
函数原型:
copy(iterator beg, iterator end, iterator dest)
常用的替换算法
repalce
功能: 将容器内指定范围的 旧元素 修改为 新元素
函数原型:
repalce(iterator beg, iterator end, oldvalue, newvalue)
repalce_if
功能: 将范围内满足条件的元素 替换成 新元素
函数原型:
repalce_if(iterator beg, iterator end, _pred, newvalue)
swap
功能: 互换两个容器的元素
函数原型:
swap(container c1, container c2);
常用的算术生成算法
accumulate
功能: 计算容器内元素累计总和
函数原型:
accumulate(iterator beg, iterator end, value);
fill
功能: 向容器中填充指定元素
函数原型:
fill(iterator beg, iterator end, value);
常用集合算法
set_intersection
功能: 求两个容器内元素的交集,并把这个交集给另一个容器
注意: 两个容器必须是有序的
函数原型:
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator target_beg)
set_union
功能: 求两个容器内元素的并集,并把这个并集给另一个容器
注意: 两个容器必须是有序的
函数原型:
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator target_beg)
set_difference
功能: 求两个容器内元素的差集,并把这个差集传给另一个容器
注意: 两个容器必须是有序的
函数原型:
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator target_beg)
差集
- v1和v2的差集是 v1-(v1和v2的交集)
- v2和v1的差集是 v2-(v1和v2的交集)
借鉴一些例子
for_each和transform
下面同过一个简单的例子,练习一下这两种遍历算法的使用:
void printArr(int val)//自定义操作:打印
{
cout << val << " ";
}
int targetArr(int val)//搬运规则函数,在原数据基础上加100
{
return val + 100;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };//原数组
int target[15];//目标数组,目标数组的长度必须不小于原数组
transform(arr, arr + 10, target, targetArr);
cout << "原数组打印:";
for_each(arr, arr + 10, printArr);
cout << "\n目标数组打印:";
for_each(target, target + 10, printArr);
}
find
下面通过两个例子练习find的使用
对于内置数据类型的使用:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
auto it = find(v.begin(), v.end(), 5);//查找元素5
if (it != v.end()) {
cout << "找到元素" << *it << endl;
}
else {
cout << "未找到元素";
}
}
对于自定义数据类型的使用:
class Person
{
public:
string m_name;
int m_age;
Person(string name,int age):m_name(name),m_age(age){}
//重载==运算符,否则find不知道按什么规则比较
bool operator==(const Person& p)
{
if (m_name == p.m_name && m_age == p.m_age) {
return true;
}
return false;
}
};
int main()
{
vector<Person> v;
v.push_back(Person("张三", 20));
v.push_back(Person("李四", 25));
v.push_back(Person("王五", 30));
v.push_back(Person("赵六", 40));
Person p("王五",30);
auto it = find(v.begin(), v.end(), p);//查找元素5
if (it != v.end()) {
cout << "找到此人:" << it->m_name << it->m_age << endl;
}
else {
cout << "未找到此人";
}
}
find_if
示例:
bool greaterFive(int val)//查找规则
{
return val > 5;
}
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
auto it = find_if(v.begin(), v.end(), greaterFive);
if (it != v.end()) {
cout << "找到大于5的元素:" << *it << endl;
}
else {
cout << "未找到" << endl;
}
}
adjacent_find
示例:
int main()
{
vector<int> v;
v.push_back(2);
v.push_back(5);
v.push_back(2);
v.push_back(3);
v.push_back(3);
auto it = adjacent_find(v.begin(), v.end());
if (it != v.end()) {
cout << "相邻重复的元素为:" << *it << endl;
}
else {
cout << "不存在相邻重复的元素" << endl;
}
}
binary_find
示例:
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
bool flag = binary_search(v.begin(), v.end(), 5);
if (flag == 1) {
cout << "找到指定元素" << endl;
}
else {
cout << "未找到" << endl;
}
}
count
示例:
我们重点看一下count在自定义数据类型中的使用
class Person
{
public:
string m_name;
int m_age;
Person(string name,int age):m_name(name),m_age(age) {}
bool operator==(const Person& p)//重载==,作为统计元素规则
{
if (m_age == p.m_age) {
return true;//统计年龄相同的元素
}
return false;
}
};
int main()
{
vector<Person> v;
v.push_back(Person("张三", 30));
v.push_back(Person("李四", 25));
v.push_back(Person("王五", 35));
v.push_back(Person("赵六", 25));
v.push_back(Person("熊大", 25));
v.push_back(Person("熊二", 20));
Person p("光头强", 25);
int num = count(v.begin(), v.end(), p);
cout << "年龄为25的生物的个数:" << num << endl;
}
count_if
示例:
bool greater5(int val)
{
return val > 5;
}
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int num = count_if(v.begin(), v.end(), greater5);
cout << "大于5的元素的个数为:" << num << endl;
}
sort
下面的一个例子将会把前面的算法for_each、transform和sort结合在一起使用
void myPrint(int val)
{
cout << val << " ";
}
int targetVector(int val)
{
return val;
}
bool myComepare(int v1,int v2)
{
return v1 > v2;
}
int main()
{
int a[10] = { 1,4,7,2,5,8,3,6,9 };//乱序数组
vector<int> v(10);
transform(a, a + 10, v.begin(), targetVector);
cout << "排序前打印数组a: ";
for_each(a, a + 10, myPrint);
cout << "\n排序前打印容器v: ";
for_each(v.begin(), v.end(), myPrint);
sort(a, a + 10);//默认升序排序
cout << "\n升序排序后打印数组a: ";
for_each(a, a + 10, myPrint);
sort(v.begin(), v.end(), myComepare);//降序排序
cout << "\n降序排序后打印容器v: ";
for_each(v.begin(), v.end(), myPrint);
}
random_shuffle
示例:
void myPrint(int val)
{
cout << val << " ";
}
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
srand((unsigned)time(NULL));//随机数种子
random_shuffle(a, a + 10);
cout << "随机打乱后:";
for_each(a, a + 10, myPrint);
}
merge
示例:
void myPrint(int val)
{
cout << val << " ";
}
int main()
{
vector<int> v;
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; ++i) {
v.push_back(i + 5);
}
vector<int> target(10 + v.size());
cout << "打印a: ";
for_each(a,a+10, myPrint);
cout << "\n打印打印v2: ";
for_each(v.begin(), v.end(), myPrint);
merge(a, a + 10, v.begin(), v.end(), target.begin());
cout << "\n打印合并后容器target: ";
for_each(target.begin(), target.end(), myPrint);
}
reverse
示例:
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
reverse(arr, arr + 10);
cout << "反转后输出:";
for (int i = 0; i < 10; ++i) {
cout << arr[i] << " ";
}
}
swap
示例:
void myPrint(int val)
{
cout << val << " ";
}
int main()
{
int a=1, b=2;
vector<int> v1,v2;
for (int i = 0; i < 10; ++i) {
v1.push_back(i); //v1: 0,1,2,3,4,5,6,7,8,9
v2.push_back(9 - i); //v2: 9,8,7,6,5,4,3,2,1,0
}
swap(a, b);
cout << "a = " << a << ", b = " << b << endl;
swap(v1, v2);
cout << "输出v1: ";
for_each(v1.begin(), v1.end(), myPrint);
cout << "\n输出v2: ";
for_each(v2.begin(), v2.end(), myPrint);
}
replace
示例:
int main()
{
int arr[10] = { 6,3,1,4,8,6,6,7,6,5 };
replace(arr + 1, arr + 10, 6, 60);
cout << "替换后:";
for (int i = 0; i < 10; ++i) {
cout << arr[i] << " ";
}
}
replace_if
示例:
bool lessFive(int val)//谓词,条件是小于5的数
{
return val < 5;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
replace_if(arr, arr + 10, lessFive, 0);
cout << "替换后:";
for (int i = 0; i < 10; ++i) {
cout << arr[i] << " ";
}
}
set_intersection
示例:
int main()
{
vector<int> v1, v2;
for (int i = 0; i < 10; ++i) {
v1.push_back(i);//v1: 0,1,2,3,4,5,6,7,8,9
v2.push_back(i + 5); //v2: 5,6,7,8,9,10,11,12,13,14
}
vector<int> target;
//设置目标容器大小
target.resize(min(v1.size(), v2.size()));
auto target_end = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), target.begin());
cout << "打印存储交集的目标容器:";
for (auto it = target.begin(); it != target_end; ++it) {
cout << *it << " ";
}
}
set_union
示例:
int main()
{
vector<int> v1, v2;
for (int i = 0; i < 10; ++i) {
v1.push_back(i);//v1: 0,1,2,3,4,5,6,7,8,9
v2.push_back(i+5); //v2: 5,6,7,8,9,10,11,12,13,14
}
vector<int> target;
//设置目标容器大小
target.resize(v1.size()+ v2.size());
auto target_end = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), target.begin());
cout << "打印存储并集的目标容器:";
for (auto it = target.begin(); it != target_end; ++it) {
cout << *it << " ";
}
}
set_difference
示例:
int main()
{
vector<int> v1, v2;
for (int i = 0; i < 10; ++i) {
v1.push_back(i);//v1: 0,1,2,3,4,5,6,7,8,9
v2.push_back(i + 5); //v2: 5,6,7,8,9,10,11,12,13,14
}
vector<int> target;
//设置目标容器大小
target.resize(max(v1.size(), v2.size()));
auto target_end = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), target.begin());
cout << "打印v1和v2的差集:";
for (auto it = target.begin(); it != target_end; ++it) {
cout << *it << " ";
}
target_end = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), target.begin());
cout << "\n打印v2和v1的差集:";
for (auto it = target.begin(); it != target_end; ++it) {
cout << *it << " ";
}
}
accumulate
示例:
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int main()
{
vector<int> v;
for (int i = 0; i <= 100; i++) {
v.push_back(i);
}
int sum = accumulate(v.begin(), v.end(), 0);
cout << "容器内元素和为:" << sum << endl;
}
fill
示例:
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int main()
{
vector<int> v(10);
fill(v.begin(), v.end(), 1);
for (int i = 0; i < 10; ++i) {
cout << v[i] << " ";
}
}
189

被折叠的 条评论
为什么被折叠?



