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;
}

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

相关推荐
酷爱码1 小时前
如何通过python连接hive,并对里面的表进行增删改查操作
开发语言·hive·python
画个大饼1 小时前
Go语言实战:快速搭建完整的用户认证系统
开发语言·后端·golang
喵先生!3 小时前
C++中的vector和list的区别与适用场景
开发语言·c++
Thomas_YXQ3 小时前
Unity3D Lua集成技术指南
java·开发语言·驱动开发·junit·全文检索·lua·unity3d
xMathematics3 小时前
计算机图形学实践:结合Qt和OpenGL实现绘制彩色三角形
开发语言·c++·qt·计算机图形学·cmake·opengl
yuanManGan6 小时前
C++入门小馆: 深入了解STLlist
开发语言·c++
北极的企鹅886 小时前
XML内容解析成实体类
xml·java·开发语言
梁下轻语的秋缘6 小时前
每日c/c++题 备战蓝桥杯(P1049 [NOIP 2001 普及组] 装箱问题)
c语言·c++·学习·蓝桥杯
BillKu6 小时前
Vue3后代组件多祖先通讯设计方案
开发语言·javascript·ecmascript
Python自动化办公社区6 小时前
Python 3.14:探索新版本的魅力与革新
开发语言·python