STL常用算法笔记

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的交集)

借鉴一些例子

例子来自【万字总结篇】C++STL常用算法详解(错等年系列)_算法c+±优快云博客

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_eachtransformsort结合在一起使用

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] << " ";
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值