STL常用算法——C++

1.概述

2.常用遍历算法

1.简介

2.for_each

方式一:传入普通函数(printf1)

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void printf1(int a)
{
	cout << a << " ";
}
int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), printf1);
	cout << endl;
	return 0;
}

方式2:利用仿函数,传入匿名函数对象

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:
	void operator()(int a)
	{
		cout << a << " ";
	}
};
int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), person());
	cout << endl;
	return 0;
}

注意:函数只需要传入函数名就行,但是仿函数需要传入函数对象。

for_each在实际开发中是最常用的一个算法,需要熟练掌握

3.transform

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class transform1
{
public:
	int operator()(int a)
	{
		return a;
	}
};
class print
{
public:
	void operator()(int a)
	{
		cout<<a<<" ";
	}
};
int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	vector<int>v1;
	v1.resize(v.size());
	transform(v.begin(), v.end(), v1.begin(), transform1());
	for_each(v.begin(), v.end(), print());
	cout << endl;
	return 0;
}

注意:转运之前,需要将目标对象用resize()也开辟相同的空间。

3.常用查找算法

1.find

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:
	person(string name, int age)
	{
		this->name = name;
		this->age = age;
	}
	bool operator==(const person& p)
	{
		if (this->age == p.age && this->name == p.name)
		{
			return true;
		}
		else return false;
	}
	string name;
	int age;
};
int main()
{
	vector<person> v;
	person p1("1", 12);
	person p2("2", 13);
	person p3("3", 14);
	person p4("4", 15);
	person p5("5", 16);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	vector<person>::iterator it = find(v.begin(), v.end(), p2);
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了" << endl;
	}
	return 0;
}

或者也可以将查找条件改为

person pp("11",13);

vector<person>::iterator it = find(v.begin(), v.end(), pp);

注意:find的返回值是迭代器

2.find_if

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	vector<int>::iterator it=find_if(v.begin(), v.end(), person());
	if (it == v.begin())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << *it << endl;
	}
	return 0;
}

3.abjacent_find

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(3);
	v.push_back(4);
	vector<int>::iterator it=adjacent_find(v.begin(), v.end());
	if (it == v.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "找到了:" << *it << endl;
	}
	return 0;
}

底层原理就是二分查找,二分查找需要提前排序好才能用,二分查找需要的算力少。

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
int main()
{
	vector<int> v;
	for(int i=0;i<10;i++)
	{
		v.push_back(i);
	}
	bool ret = binary_search(v.begin(), v.end(),9);
	if (ret)
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}
	return 0;
}

如果是无序序列,结果未知

5.count

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:
	person(string name, int age)
	{
		this->age = age;
		this->name = name;
	}
	bool operator==(const person& p)
	{
		if (p.age == this->age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	int age;
	string name;
};
int main()
{
	vector<person> v;
	person p1("刘备", 35);
	person p2("关羽", 35);
	person p3("张飞", 35);
	person p4("赵云", 20);
	person p5("刘备", 40);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	person p("诸葛亮", 35);
	int a = count(v.begin(), v.end(), p);
	cout << "同年龄的有:" << a << "个" << endl;
	return 0;
}

关于为什么operator要加const

const Person p1("刘备", 35);

Person p2("关羽", 35);

if (p1 == p2)

{

// 编译错误:无法将 const 对象传递给非 const 引用参数

cout << "年龄相同" << endl;

}

在运算符重载中,参数通常也会被声明为const 。这样做的目的是为了扩大函数的适用范围,使其既能接受const 对象,也能接受非const对象。

总结:对于统计自定义数据类型的时候,需要配合重载operator==

对于形参是自定义类型时,要加上const

6.count_if

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
class person
{
public:
	bool operator()(int val)
	{
		return val == 2;
	}
};
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(2);
	v.push_back(2);
	v.push_back(5);
	int a = count_if(v.begin(), v.end(), person());
	cout << "同年龄的有:" << a << "个" << endl;
	return 0;
}

4.常用排序算法

1.sort

pred是谓词

生序

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void print(int a)
{
	cout << a << " ";
}
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(6);
	v.push_back(3);
	v.push_back(5);
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), print);
	return 0;
}

降序(利用内建函数对象greater实现降序排序,要包含头文件functional)

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{
	cout << a << " ";
}
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(6);
	v.push_back(3);
	v.push_back(5);
	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(),fun);
	return 0;
}

2.random_shuffle

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{
	cout << a << " ";
}
int main()
{
	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(),fun);
	return 0;
}

可以加入时间种子来达到真随机效果(srand(unsigned int)time(NULL);)

不过需要包含头文件#include<time.h>

3.merge

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{
	cout << a << " ";
}
int main()
{
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i+1);
	}
	v3.resize(v1.size() + v2.size());
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(), v3.end(),fun);
	return 0;
}

不过要给目标容器提前开辟内存空间用resize

而且合并之后还是一个有序序列

merge合并的两个序列必须是有序序列

4.reverse

5.常用拷贝和替换算法

1.copy

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{
	cout << a << " ";
}
int main()
{
	vector<int> v1;
	vector<int> v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	v2.resize(v1.size());
	copy(v1.begin(), v1.end(), v2.begin());
	for_each(v2.begin(), v2.end(),fun);
	return 0;
}

2.replace

3.replace_if

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	replace_if(v1.begin(), v1.end(), person(), 1000);
	for_each(v1.begin(), v1.end(),fun);
	return 0;
}

可以利用仿函数灵活的设置筛选条件

4.swap

cpp 复制代码
swap(v1,v2);

其中两个容器的大小和数值都会交换,不过交换的容器要同种类型

6.常用算术生成算法

1.accumulate

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	for (int i = 0; i <= 100; i++)
	{
		v1.push_back(i);
	}
	int val=accumulate(v1.begin(),v1.end(),0);
	/*for_each(v1.begin(), v1.end(),fun);*/
	cout << val << endl;
	return 0;
}

比较实用,记住要添加头文件#include<numeric>

2.fill

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	fill(v1.begin(),v1.end(),99);
	for_each(v1.begin(), v1.end(),fun);
	cout << endl;
	vector<int> v2;
	v2.resize(10);
	fill(v2.begin(), v2.end(), 11);
	for_each(v2.begin(), v2.end(), fun);
	return 0;
}

如果已经有了数值,会把原来的数值顶替掉

7.常用集合算法

1.set_intersection

交集:即两个容器中数值相同的元素

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	vector<int> v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i+3);
	}
	vector<int>v3;
	v3.resize(min(v1.size(), v2.size()));
	vector<int>::iterator it=set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(),it,fun);
	cout << endl;
	return 0;
}

注意:

set_intersection其中它会返回交际的最后一个元素的迭代器,遍历输出交集的时候不要写end(),要写它返回的迭代器,这样就不会输出无用元素。

存储交集的目标容器需要提前开辟空间,最特殊的情况是大容器包含小容器,即交集就是小容器,所以取小容器的大小即可。

min()包含在algorithm头文件中,找出最小值

2.set_union

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	vector<int> v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i+3);
	}
	vector<int>v3;
	v3.resize(v1.size()+v2.size());
	vector<int>::iterator it=set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(),it,fun);
	cout << endl;
	return 0;
}

最坏的情况是一个相同的都没有,所以开辟大小直接把两个容器的大小加起来就行

注意:两个容器必须是有序序列

3.set_different

有两种差集的情况:(谁在前先求谁的差集)

cpp 复制代码
#include<stdio.h>
using namespace std;
#include<string>
#include<vector>
#include<functional>
#include<algorithm>
#include <iostream>
#include<numeric>
void fun(int a)
{
	cout << a << " ";
}
class person
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};
int main()
{
	vector<int> v1;
	vector<int> v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i+3);
	}
	v2.push_back(99);
	vector<int>v3;
	v3.resize(max(v1.size(),v2.size()));
	vector<int>::iterator it=set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(),it,fun);
	cout << endl;
	vector<int>::iterator it1 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v3.begin());
	for_each(v3.begin(), it1, fun);
	cout << endl;
	return 0;
}

注意:两个容器必须是有序序列

相关推荐
随风一样自由11 小时前
React编码时,什么时候用js文件,什么时候用jsx文件?
开发语言·javascript·react.js
by__csdn11 小时前
Vue3 生命周期全面解析:从创建到销毁的完整指南
开发语言·前端·javascript·vue.js·typescript·前端框架·ecmascript
小年糕是糕手11 小时前
【C++同步练习】模板初阶
服务器·开发语言·前端·javascript·数据库·c++·改行学it
永远不打烊11 小时前
c++11 之 智能指针
c++
weixin_3077791311 小时前
Jenkins Folders插件详解:组织、管理与最佳实践
运维·开发语言·自动化·jenkins
raoxiaoya11 小时前
golang调用 elasticsearch 8,向量检索
开发语言·elasticsearch·golang
deng-c-f11 小时前
C/C++内置库函数(2):智能指针
java·c语言·c++
yuhaiqun198911 小时前
新手练 C++ HTTP 服务实操:从 “拆请求头” 到 “发 HTML 响应”
c语言·c++·程序人生·http·html·学习方法·改行学it
小年糕是糕手11 小时前
【C/C++刷题集】类和对象算法题(一)
数据结构·c++·程序人生·考研·算法·leetcode·改行学it
爱上妖精的尾巴11 小时前
6-5 WPS JS宏 集合成员迭代(随机生成试题)
开发语言·前端·javascript