STL-标准模板库

发布于:2024-04-23 ⋅ 阅读:(19) ⋅ 点赞:(0)

STL的诞生

  • 长久以来,软件界一直希望建立一种可重复利用的东西
  • c++的面向对象和泛型编程思想,目的就是复用性的提升
  • 大多数情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
  • 为了建立数据结构和算法的一套标准,诞生了STL

STL基本概念

  • STL(Standard Template Library)标准模板库
  • STL 从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
  • 容器和算法之间通过迭代器进行无缝连接
  • STL几乎所有的代码都采用了模板类或者模板函数

STL六大组件

六大组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

  1. 容器:各种数据结构,如 vector、list、deque、set、map 等,用来存放数据
  2. 算法:各种常用的算法,如 sort、find、copy、for_each 等
  3. 迭代器:扮演了容器与算法之间的胶合剂
  4. 仿函数:行为类似函数,可作为算法的某种策略
  5. 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
  6. 空间配置器:负责空间的配置与管理

String 容器

基本概念

本质

  • string 是 C++ 风格的字符串,而 string 本质上是一个类

string 和 char* 区别

  • char* 是一个指针,通过这个指针管理一连串的 char 类型的空间
  • string 是一个类,类内部封装了 char*,管理这个字符串,是一个 char* 类型的容器

特点

string 类内部封装了很多成员方法

例如:查找 find,拷贝 copy,删除 delete,替换 replace,插入 insert

string 管理 char* 所分配的内存,不用担心复制越界和取值越界等问题,这些问题由类内部进行负责

构造函数

#include <iostream>
#include <string>
using namespace std;


void test()
{
	string s1;	// 背后会调用默认的构造函数

	const char* s2 = "hello world";		// C语言风格的字符串

	string s3(s2);	// 背后会调用拷贝构造函数
	cout << s3 << endl;

	string s4(5, 'a');
	cout << s4 << endl;		// 输出结果:aaaaa
}

int main()
{
	test();
}

赋值操作

#include <iostream>
#include <string>
using namespace std;


void test()
{
	string s1;
	s1 = "hello world";
	cout << s1 << endl;

	string s2;
	s2 = s1;
	cout << s2 << endl;

	string s3;
	s3 = 'a';
	cout << s3 << endl;

	string s4;
	s4.assign("hello world");
	cout << s4 << endl;

	string s5;
	s5.assign("hello world", 5);	// 前5个字符将会赋值给字符串
	cout << s5 << endl;

	string s6;
	s6.assign(s5);
	cout << s6 << endl;

	string s7;
	s7.assign(6, 'a');	// 等价于 s7 = "aaaaaa"
	cout << s7 << endl;
}

int main()
{
	test();
}

字符串拼接

#include <iostream>
#include <string>
using namespace std;


void test()
{
	string s1 = "我";
	s1 += "爱唱歌";		// 追加字符串
	s1 += 'a';			// 追加一个字符

	string s2 = "666";
	s1 += s2;

	string s3 = "I";
	s3.append(" Love ");

	s3.append("game abcde", 4);		// 只追加前面4个字符
	cout << s3 << endl;		// 输出结果:I Love game

	s3.append(s2);
	s3.append(s2, 0, 4);	// 从第0个位置开始追加字符,只追加4个
}

int main()
{
	test();
}

查找和替换

#include <iostream>
#include <string>
using namespace std;


void test()
{
	// 查找
	string s1 = "abcdefg";
	int position = s1.find("de");	// 第一次出现"de"的位置
	cout << position << endl;		// 输出结果:3

	position = s1.rfind("ef");		// right-find 从右开始查找

	// 替换
	string s2 = "abcde";
	s2.replace(1, 3, "kkkk");	// 从1号位置起的3个字符,替换为 kkkk
}


int main()
{
	test();
}

字符串比较

#include <iostream>
#include <string>
using namespace std;


void test()
{
	// 字符串比较大小---ASCII码 比较大小
	string s1 = "hello";
	string s2 = "abcdef";

	int ret = s1.compare(s2);

	if (ret == 0)
	{
		cout << "s1 == s2" << endl;
	}
	else if (ret > 0)
	{
		cout << "s1 > s2" << endl;
	}
	else
	{
		cout << "s1 < s2" << endl;
	}
}

int main()
{
	test();
}

单个字符存取

#include <iostream>
#include <string>
using namespace std;


void test()
{
	string s1 = "hello";

	// 1. 通过 [] 访问单个字符
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i];
	}

	cout << endl;

	// 2. 通过 at 方式访问单个字符
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1.at(i);
	}

	// 修改单个字符
	s1[0] = 'k';
	s1.at(0) = 'm';
}

int main()
{
	test();
}

插入与删除

#include <iostream>
#include <string>
using namespace std;


void test()
{
	string s = "hello";

	// 插入
	s.insert(1, "vvv");
	cout << s << endl;		// hvvvello

	// 删除
	s.erase(1, 3);			// 从1号位开始删除,删除3个
	cout << s << endl;		// hello
}

int main()
{
	test();
}

子串获取

#include <iostream>
#include <string>
using namespace std;


void test()
{
	// 获取子串
	string s1 = "hello";
	string s2 = s1.substr(1, 3);
	cout << s2 << endl;			// 输出结果:ell

	// 应用
	string email = "jack@qq.com";
	int position = email.find("@");
	string username = email.substr(0, position);
	cout << "username: " << username << endl;	// 输出结果:jack
}

int main()
{
	test();
}

vector 容器

存放内置数据类型

#include <iostream>
#include <vector>
#include <algorithm>	// 标准算法头文件
using namespace std;


// vector 容器存放内置数据类型


// myPrint函数声明
void myPrint(int val);

void test()
{
	// 创建一个vector容器
	vector<int> v;

	// 向容器中插入数据
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);

	// 通过迭代器访问容器中的数据
	vector<int>::iterator itBegin = v.begin();	// 起始迭代器	指向容器中第一个元素
	vector<int>::iterator itEnd = v.end();		// 结束迭代器 指向容器中最后一个元素的下一个位置

	// 第一种遍历方式
	while (itBegin != itEnd)
	{
		cout << *itBegin << endl;
		itBegin++;
	}

	// 第二种遍历方式
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << endl;
	}

	// 第三种遍历方式(利用STL提供遍历算法)
	for_each(v.begin(), v.end(), myPrint);
}

// myPrint函数实现
void myPrint(int val)
{
	cout << val << endl;
}

int main()
{
	test();
}

存放自定义数据类型

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;


// vector容器中存放自定义数据类型


class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

void test()
{
	// 准备好vector容器
	vector<Person> v;

	// 准备好数据
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);
	Person p5("eee", 50);

	// 向容器中添加数据
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	// 遍历容器中的数据
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "姓名:" << (*it).m_Name << "  年龄:" << (*it).m_Age << endl;
	}
}

int main()
{
	test();
}

vector 容器的嵌套

#include <iostream>
#include <vector>
using namespace std;


// 容器中嵌套容器

void test()
{
	// 准备一个外层容器
	vector< vector<int> > v;

	// 准备一些内层容器
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;
	vector<int> v5;

	// 向内层容器添加数据
	for (int i = 0; i < 4; i++)
	{
		v1.push_back(i + 1);
		v2.push_back(i + 1);
		v3.push_back(i + 1);
		v4.push_back(i + 1);
		v5.push_back(i + 1);
	}

	// 将内层容器插入到外层容器中
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	v.push_back(v4);
	v.push_back(v5);

	// 遍历取出数据
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		for (vector<int>::iterator itt = (*it).begin(); itt != (*it).end(); itt++)
		{
			cout << *itt << " ";
		}
		cout << endl;
	}
}

int main()
{
	test();
}

/*
	运行结果:
		1 2 3 4
		1 2 3 4
		1 2 3 4
		1 2 3 4
		1 2 3 4
*/

构造函数

#include <iostream>
#include <vector>
using namespace std;

// vector 容器构造

void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// 通过默认的无参构造函数来实现构造
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);

	// 通过区间方式进行构造
	vector<int> v2(v1.begin(), v1.end());
	printVector(v2);

	// n个element方式构造
	vector<int> v3(10, 100);	// 10 个 100
	printVector(v3);

	// 拷贝构造
	vector<int> v4(v3);
	printVector(v4);
}

int main()
{
	test();
}

赋值操作

#include <iostream>
#include <vector>
using namespace std;

// vector 赋值操作

void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);		// 0 1 2 3 4 5 6 7 8 9

	// 通过符号"="实现
	vector<int> v2;
	v2 = v1;
	printVector(v2);		// 0 1 2 3 4 5 6 7 8 9

	// 通过 assign 实现
	vector<int> v3;
	v3.assign(v1.begin(), v1.end());
	printVector(v3);		// 0 1 2 3 4 5 6 7 8 9

	// 通过 n 个 element 实现
	vector<int> v4;
	v4.assign(10, 99);
	printVector(v4);		// 99 99 99 99 99 99 99 99 99 99
}

int main()
{
	test();
}

容量和大小

#include <iostream>
#include <vector>
using namespace std;


void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// vector 容器的容量和大小操作
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);		// 0 1 2 3 4 5 6 7 8 9

	if (v1.empty())
	{
		cout << "v1为空" << endl;
	}
	else
	{
		cout << "v1不为空" << endl;
		cout << "v1的容量为:" << v1.capacity() << endl;
		cout << "v1的大小为:" << v1.size() << endl;
	}

	// 重新指定大小
	v1.resize(15, 0);	// 第二个参数可以不写,默认填充值为0
	printVector(v1);	// 如果重新指定的比原来的长,默认用0填充

	v1.resize(5);
	printVector(v1);	// 如果重新指定的比原来的短,超出部分将会被删除
}

int main()
{
	test();
}

插入和删除

#include <iostream>
#include <vector>
using namespace std;


void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// vector 插入与删除
	
	vector<int> v1;

	// 尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);

	printVector(v1);					// 输出结果:10 20 30 40 50

	// 尾删
	v1.pop_back();
	printVector(v1);					// 输出结果:10 20 30 40


	// 插入	<-第一个参数是迭代器->
	v1.insert(v1.begin(), 99);			// 在头部插入数据 99
	printVector(v1);					// 输出结果:99 10 20 30 40

	v1.insert(v1.begin(), 2, 888);		// 在头部插入两个数据 888
	printVector(v1);					// 输出结果:888 888 99 10 20 30 40


	// 删除	<-第一个参数是迭代器->
	v1.erase(v1.begin());				// 在头部删除一个数据
	printVector(v1);					// 输出结果:888 99 10 20 30 40

	v1.erase(v1.begin(), v1.end());		// 从头部开始删除,一直删除到尾部(也就是清空)
	v1.clear();							// 直接清空
	printVector(v1);					// 输出结果:""
}

int main()
{
	test();
}

数据存取

#include <iostream>
#include <vector>
using namespace std;


void test()
{
	vector<int> v1;

	// ----------- 存取数据 ----------- 
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	// ----------- 输出数据 ----------- 
	for (int i = 0; i < v1.size(); i++)
	{
		// 利用 [] 方式访问数组中的元素
		cout << v1[i] << " ";
	}
	cout << endl;

	// ----------- 输出数据 ----------- 
	for (int i = 0; i < v1.size(); i++)
	{
		// 利用 at 方式访问元素
		cout << v1.at(i) << " ";
	}
	cout << endl;

	// 获取第一个元素
	cout << "第一个元素为:" << v1.front() << endl;
	cout << "最后一个元素为:" << v1.back() << endl;
}

int main()
{
	test();
}

/*
	运行结果:
		0 1 2 3 4 5 6 7 8 9
		0 1 2 3 4 5 6 7 8 9
		第一个元素为:0
		最后一个元素为:9
*/

互换容器

#include <iostream>
#include <vector>
using namespace std;

// 输出容器内容
void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test1()
{
	// 容器1
	vector<int> v1;
	
	// 添加数据
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);		// 0 1 2 3 4 5 6 7 8 9


	// 容器2
	vector<int> v2;
	
	for (int i = 10; i > 0; i--)
	{
		v2.push_back(i);
	}
	printVector(v2);		// 10 9 8 7 6 5 4 3 2 1


	// 交换容器
	/*
		v1 指向 容器1
		v2 指向 容器2
		------------
		交换容器之后
		------------
		v1 指向 容器2
		v2 指向 容器1
	*/
	v1.swap(v2);
	printVector(v1);		// 10 9 8 7 6 5 4 3 2 1
	printVector(v2);		// 0 1 2 3 4 5 6 7 8 9
}

void test2()
{
	// 交换容器的实际应用:巧用swap可以收缩空间内存

	// 1. 创建一个vector容器
	vector<int> v;
	

	// 2. 向容器里面添加1000个数据
	for (int i = 0; i < 1000; i++)
	{
		v.push_back(i);
	}
	cout << endl;
	cout << "v的容量为:" << v.capacity() << endl;		// 输出结果:v的容量为:1066
	cout << "v的大小为:" << v.size() << endl;			// 输出结果:v的大小为:1000


	// 3. 重新指定大小
	v.resize(30);		// 意味着原来使用了1000个数据,现在只用了30个,剩下的大量空间都被浪费了
	cout << endl;
	cout << "v的容量为:" << v.capacity() << endl;		// 输出结果:v的容量为:1066
	cout << "v的大小为:" << v.size() << endl;			// 输出结果:v的大小为:30
	
	// 4. 巧用swap收缩内存
	/*
		原理:利用"匿名对象"创建出来没多久就会被系统自动回收的特点
		
		有名对象:
			vector<int> v		// 无参
			vector<int> v(...)	// 含参

		匿名对象:
			vector<int>()		// 无参
			vector<int>(v)		// 含参or拷贝

		具体实现:
			1. 复制v容器的30个数据,创建一个匿名对象容器 (到时候系统会自动回收)
			2. 马上让它和v容器进行互换
					v		--->	容量为1066的容器
					匿名		--->	容量为30的容器
					---------- 互换后 ------------
					v		--->	容量为30的容器
					匿名		--->	容量为1066的容器
			3. 语句结束,系统马上回收匿名对象容器 (即: 回收了容量为1066的容器)
	*/
	vector<int> (v).swap(v);	// 创建匿名对象容器,并马上交换容器
	cout << endl;
	cout << "v的容量为:" << v.capacity() << endl;		// 输出结果:v的容量为:30
	cout << "v的大小为:" << v.size() << endl;			// 输出结果:v的大小为:30
}

int main()
{
	test1();
	test2();
}

预留空间

#include <iostream>
#include <vector>
using namespace std;


void test()
{
	vector<int> v;
	v.reserve(1000);	// 利用reserve预留空间,可以减少因为容器容量不足而重新开辟内存的次数

	int num = 0;		// 统计开辟次数
	int* p = NULL;
	for (int i = 0; i < 1000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout << "开辟次数 num = " << num << endl;			// 开辟次数 num = 1
	cout << "容器容量:" << v.capacity() << endl;		// 容器容量:1000
	cout << "容器大小:" << v.size() << endl;			// 容器容量:1000
}

int main()
{
	test();
}

deque 容器

构造函数

#include <iostream>
#include <deque>
using namespace std;

void printDeque(deque<int>& d)
{
	for (deque<int>::iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}
	printDeque(d1);

	deque<int> d2(d1.begin(), d1.end());
	printDeque(d2);

	deque<int> d3(10, 99);
	printDeque(d3);

	deque<int> d4(d3);
	printDeque(d4);
}

int main()
{
	test();
}

赋值操作

  • 与 vector 操作一样

容量和大小

  • deque 没有容量的概念
  • 判断是否为空 — empty
  • 返回元素个数 — size
  • 重新指定个数 — resize

插入和删除

#include <iostream>
#include <deque>
using namespace std;

// 输出容器数据
void printDeque(deque<int>& d)
{
	for (deque<int>::iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	deque<int> d1;
	
	// 尾插
	d1.push_back(10);
	d1.push_back(20);
	printDeque(d1);			// 10 20

	// 头插
	d1.push_front(66);
	d1.push_front(88);
	printDeque(d1);			// 88 66 10 20

	// 尾删
	d1.pop_back();
	printDeque(d1);			// 88 66 10

	// 头删
	d1.pop_front();
	printDeque(d1);			// 66 10

	// 插入
	d1.insert(d1.begin(), 99);
	printDeque(d1);			// 99 66 10

	d1.insert(d1.begin(), 2, 77);
	printDeque(d1);			// 77 77 99 66 10

	// 按照区间进行插入
	deque<int> d2;
	d2.push_back(111);
	d2.push_back(222);
	d2.push_back(333);
	printDeque(d2);			// 111 222 333

	d1.insert(d1.begin(), d2.begin(), d2.end());
	printDeque(d1);			// 111 222 333 77 77 99 66 10

	// 删除
	deque<int>::iterator it = d1.begin();
	it++;
	d1.erase(it);
	printDeque(d1);			// 111 333 77 77 99 66 10

	// 按照区间的方式进行删除
	d1.erase(d1.begin(), d1.end());		// 等价于清空操作:  d1.clear();
	printDeque(d1);			// 空
}

int main()
{
	test();
}

存取操作

  • 除了用迭代器获取 deque 容器中的元素,[ ] 和 at 也可以
  • front 返回容器第一个元素
  • back 返回容器最后一个元素

排序

#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;

// 输出容器数据
void printDeque(deque<int>& d)
{
	for (deque<int>::iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_back(30);
	d.push_front(100);
	d.push_front(200);
	d.push_front(300);

	printDeque(d);		// 300 200 100 10 20 30

	// 排序 
	// 1. 默认排序规则:从小到大的升序排序
	// 2. 对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序,使用它之前记得 #include <algorithm>
	sort(d.begin(), d.end());
	printDeque(d);		// 10 20 30 100 200 300
}

int main()
{
	test();
}

vector 与 deque 案例

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <ctime>
using namespace std;

/*
	有5名选手:选手ABCDE,10个评委分别对每一位选手打分
	去除最高分,去除评委中最低分,取平均分
*/


// 选手类:负责维护选手信息
class Person
{
public:
	Person(string name, int score) :m_Name(name), m_Score(score)
	{
		cout << "成功构造了一名选手!" << endl;
	}

	string m_Name;
	int m_Score;
};


// 创建选手,并且放入到容器中
void createPerson(vector<Person>& v)
{
	string nameSeed = "ABCDE";
	int score = 0;
	for (int i = 0; i < 5; i++)
	{
		string name = "选手";
		name += nameSeed[i];
		
		Person p(name, score);
		v.push_back(p);		// 将创建的Person对象 放入到容器中		
	}
}


// 输出容器中的数据
void printVector(vector<Person>& v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "{" << (*it).m_Name << ", " << (*it).m_Score << "}" << endl;
	}
}

// 给选手打分
void setScore(vector<Person>& v)
{
	// 从容器中,获取每一个选手,修改选手里面默认的score数据
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		// 1. 准备score数据:
		// 1.1. 准备好一个容器
		deque<int> d;

		// 1.2. 随机出10个数,将它们放到容器中
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 41 + 60;		// 60 ~ 100
			d.push_back(score);
		}

		// 1.3. 将分数进行排序
		sort(d.begin(), d.end());	// 默认升序-由小到大

		// 1.4. 去除最高和最低分
		d.pop_back();
		d.pop_front();

		// 1.5. 取平均分
		int sum = 0;
		for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
		{
			sum += (*dit);
		}
		int average = (int)(sum / d.size());

		// 2. 修改score数据
		(*it).m_Score = average;
	}
}

void test()
{
	// 随机数种子
	srand((unsigned int)time(NULL));

	// 1. 创建5名选手
	vector<Person> v;			// 创建容器
	createPerson(v);			// 创建选手,并放入容器中
	cout << "-----------------------" << endl;
	printVector(v);				// 插入容器中的数据(选手)
	
	// 2. 给5名选手打分
	setScore(v);
	cout << "-----------------------" << endl;
	
	// 3. 显示最后得分
	printVector(v);
}
 
int main()
{
	test();
}

/*
	运行结果:
		成功构造了一名选手!
		成功构造了一名选手!
		成功构造了一名选手!
		成功构造了一名选手!
		成功构造了一名选手!
		-----------------------
		{选手A, 0}
		{选手B, 0}
		{选手C, 0}
		{选手D, 0}
		{选手E, 0}
		-----------------------
		{选手A, 78}
		{选手B, 82}
		{选手C, 74}
		{选手D, 80}
		{选手E, 77}
*/

stack 容器

#include <iostream>
#include <stack>

using namespace std;

void test()
{
	// stack(栈)容器
	stack<int> s;

	// 查看栈的大小
	cout << "栈的大小:" << s.size() << endl;

	// 入栈
	s.push(10);
	s.push(20);
	s.push(30);

	// 查看栈的大小
	cout << "栈的大小:" << s.size() << endl;

	// 只要栈不为空,查看栈顶,并且执行出栈操作
	while (!s.empty())
	{
		// 查看栈顶元素
		cout << "栈顶元素为:" << s.top() << endl;

		// 出栈
		s.pop();
	}

	// 查看栈的大小
	cout << "栈的大小:" << s.size() << endl;
}

int main()
{
	test();
}

/*
	运行结果:
		栈的大小:0
		栈的大小:3
		栈顶元素为:30
		栈顶元素为:20
		栈顶元素为:10
		栈的大小:0
*/

queue 容器

#include <iostream>
#include <queue>

using namespace std;

class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	string m_Name;
	int m_Age;
};

void test()
{
	// 创建队列
	queue<Person> q;

	// 准备数据
	Person p1("Jack", 20);
	Person p2("Tom", 30);
	Person p3("Peter", 40);
	Person p4("Jim", 50);

	cout << "队列大小:" << q.size() << endl;

	// 入队
	q.push(p1);
	q.push(p2);
	q.push(p3);
	q.push(p4);

	cout << "队列大小:" << q.size() << endl;

	// 判断只要队列不为空,查看队头,查看队尾,然后出队
	while (!q.empty())
	{
		// 查看对头
		cout << "队头元素:{" << q.front().m_Name << ", " << q.front().m_Age << "}\t";

		// 查看队尾
		cout << "队尾元素:{" << q.back().m_Name << ", " << q.back().m_Age << "}" << endl;

		// 出队
		q.pop();
	}

	cout << "队列大小:" << q.size() << endl;
}

int main()
{
	test();
}

list 容器

基本认识

功能:将数据进行链式存储
链表(list):是一种物理存储单元上非连续的存储结构
STL中的链表是双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

构造函数

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// 默认构造
	list<int> l1;		// 创建list容器

	// 添加数据
	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	l1.push_back(40);

	// 遍历容器
	printList(l1);			// 10 20 30 40

	// 区间方式构造
	list<int> l2(l1.begin(), l1.end());
	printList(l2);			// 10 20 30 40

	// 拷贝构造
	list<int> l3(l2);
	printList(l3);			// 10 20 30 40

	// n个element
	list<int> l4(10, 99);
	printList(l4);			// 99 99 99 99 99 99 99 99 99 99
}

int main()
{
	test();
}

赋值与交换

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// 准备一个list容器
	list<int> l1;

	// 装入数据
	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	l1.push_back(40);

	printList(l1);		// 10 20 30 40

	list<int> l2;
	l2 = l1;		// operator= 赋值
	printList(l2);		// 10 20 30 40

	list<int> l3;
	l3.assign(l2.begin(), l2.end());	// assign 赋值
	printList(l3);		// 10 20 30 40

	list<int> l4;
	l4.assign(10, 88);		// 10个88
	printList(l4);		// 88 88 88 88 88 88 88 88 88 88

	// 交换
	list<int> l5, l6;
	l5.assign(6, 111);
	l6.assign(6, 222);
	l5.swap(l6);
	printList(l5);		// 222 222 222 222 222 222
	printList(l6);		// 111 111 111 111 111 111
}

int main()
{
	test();
}

大小操作

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	// 创建list容器,并存入数据
	list<int> l1;
	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	printList(l1);		// 10 20 30

	// 判断容器是否为空
	if (l1.empty())
	{
		cout << "l1为空" << endl;
	}
	else
	{
		cout << "l1不为空" << endl;							// l1不为空
		cout << "l1的元素个数为:" << l1.size() << endl;		// l1的元素个数为:3
	}

	// 重新指定大小
	l1.resize(10, 666);		// 第一个参数是重新指定大小为10,第二个参数是使用666填充,如果第二个参数不传入,默认填充值是0
	printList(l1);

}

int main()
{
	test();
}

插入和删除

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	list<int> l;

	// 尾插
	l.push_back(10);
	l.push_back(20);
	l.push_back(30);

	// 头插
	l.push_front(11);
	l.push_front(22);
	l.push_front(33);

	printList(l);		// 33 22 11 10 20 30

	// 尾删
	l.pop_back();
	l.pop_front();
	printList(l);		// 22 11 10 20

	// 插入
	l.insert(l.begin(), 3333);
	printList(l);		// 3333 22 11 10 20

	// 删除
	l.erase(l.begin());
	printList(l);		// 22 11 10 20

	// 移除
	l.remove(10);		// 移除容器中所有的和指定内容匹配的值
	printList(l);		// 22 11 20
}

int main()
{
	test();
}

数据存取

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	list<int> l;
	l.push_back(10);
	l.push_back(20);
	l.push_back(30);

	// list容器不可以用 [] 访问容器中的元素
	// list容器不可以用 at 访问容器中的元素
	// 原因:list容器本质是一个链表,不是用连续的线性空间存储数据,迭代器也是不支持随机访问的

	cout << "第一个元素:" << l.front() << endl;
	cout << "最后一个元素:" << l.back() << endl;

	// list容器的迭代器不支持随机访问
	// 例如:it+3、it+19 是不允许的
	// 但是它支持双向访问,即 it++ 与 it--
	list<int>::iterator it = l.begin();
	it++;
	it--;
}

int main()
{
	test();
}

反转和排序

#include <iostream>
#include <list>

using namespace std;

void printList(const list<int> &l)
{
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test()
{
	list<int> l;
	l.push_back(20);
	l.push_back(50);
	l.push_back(40);
	l.push_back(10);
	l.push_back(30);

	cout << "反转前:" << endl;
	printList(l);		// 20 50 40 10 30

	l.reverse();

	cout << "反转后:" << endl;
	printList(l);		// 30 10 40 50 20


	// 所有不支持随机访问迭代器的容器,不可以使用标准算法
	// 不支持随机访问迭代器的容器,内部会提供对应的一些算法
	// sort(l.begin(), l.end());

	cout << "排序前:" << endl;
	printList(l);		// 30 10 40 50 20

	l.sort();			// 默认排序规则:从小到大,升序

	cout << "排序后:" << endl;
	printList(l);		// 10 20 30 40 50
}

int main()
{
	test();
}

排序案例

#include <iostream>
#include <list>

using namespace std;

class Person
{
public:
	Person(string name, int age, int height)
	{
		this->m_Name = name;
		this->m_Age = age;
		this->m_Height = height;
	}

	string m_Name;
	int m_Age;
	int m_Height;
};

// 排序规则函数
bool comparePerson(Person& p1, Person& p2)
{
	// 按照年龄从小到大的顺序进行排序--升序
	// 如果年龄相同,则按照身高升序进行排序
	if (p1.m_Age == p2.m_Age)
	{
		return p1.m_Height < p2.m_Height;
	}
	return p1.m_Age < p2.m_Age;
}

void test()
{
	// 创建容器
	list<Person> l;

	// 准备数据
	Person p1("Peter", 28, 180);
	Person p2("Jack", 18, 170);
	Person p3("Tom", 18, 160);

	// 插入数据
	l.push_back(p1);
	l.push_back(p2);
	l.push_back(p3);

	cout << "排序前:" << endl;

	// 查看容器中的数据
	for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
	{
		cout << "{姓名:" << (*it).m_Name << ", 年龄:" << (*it).m_Age << ", 身高:" << (*it).m_Height << "cm}" << endl;
	}
	
	// 排序
	l.sort(comparePerson);		// 编写"排序规则函数"
	cout << "排序后:" << endl;

	// 查看容器中的数据
	for (list<Person>::iterator it = l.begin(); it != l.end(); it++)
	{
		cout << "{姓名:" << (*it).m_Name << ", 年龄:" << (*it).m_Age << ", 身高:" << (*it).m_Height << "cm}" << endl;
	}
}

int main()
{
	test();
}

Set 容器

基本认识

简介:
	所有元素都会在插入时自动被排序

本质:
	set/multiset 属于关联式容器,底层结构是用二叉树实现
	
set和multiset区别:
	set不允许容器中有重复的元素
	multiset允许容器中有重复的元素

构造和赋值

#include <iostream>
#include <set>
using namespace std;

void printSet(set<int>& s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}


void test()
{
	// 默认构造
	set<int> s1;

	// 插入数据 只有insert方法
	// set容器的特点:所有元素插入时候自动被排序
	// set容器不允许插入重复值
	s1.insert(30);
	s1.insert(10);
	s1.insert(40);
	s1.insert(20);

	printSet(s1);		// 10 20 30 40
	
	// 拷贝构造
	set<int> s2(s1);
	printSet(s2);		// 10 20 30 40

	// 赋值
	set<int> s3;
	s3 = s2;
	printSet(s3);		// 10 20 30 40
}

int main()
{
	test();
}

大小和交换

size();		返回容器中元素的数目
empty();	判断容器是否为空
swap(st);	交换两个集合容器

插入和删除

insert(element);		在容器中插入元素
clear();				清除所有元素
erase(position);		删除position迭代器所指向的元素,返回下一个元素的迭代器
erase(beg, end);		删除区间[beg, end)的所有元素,返回下一个元素的迭代器
erase(element);			删除容器中值为element的元素

查找和统计

#include <iostream>
#include <set>
using namespace std;

// set容器 查找和统计

void test()
{
	// 创建容器
	set<int> s1;

	// 插入数据
	s1.insert(20);
	s1.insert(40);
	s1.insert(10);
	s1.insert(30);

	// 查找
	set<int>::iterator pos = s1.find(30);
	if (pos != s1.end())
	{
		cout << "找到元素:" << *pos << endl;
	}
	else
	{
		cout << "未找到元素" << endl;
	}

	// 统计30的个数(对于set而言,统计的结果要么是0,要么是1)
	int num = s1.count(30);
	cout << "num = " << num << endl;
}

int main()
{
	test();
}

set 和 multiset 区别

#include <iostream>
#include <set>
using namespace std;

// set 不可以插入重复数据,而multiset可以
// set 插入数据的同时会返回插入结果,表示插入是否成功
// multiset 不会检测数据,因此可以插入重复数据

void test()
{
	// 这个容器允许插入重复的值
	multiset<int> ms;
	ms.insert(10);
	ms.insert(10);
	ms.insert(10);

	// 输出容器中的数据
	for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;		// 10 10 10


}

int main()
{
	test();
}

pair 对组

功能描述:成对出现的数据,利用对组可以返回两个数据
#include <iostream>
#include <set>
using namespace std;

// pair对组的创建
void test()
{
	// 第一种方式
	pair<string, int> p1("Tom", 28);
	cout << p1.first << " " << p1.second << endl;		// Tom 28

	// 第二种方式
	pair<string, int> p2 = make_pair("Jerry", 30);
	cout << p2.first << " " << p2.second << endl;		// Jerry 30
}

int main()
{
	test();
}

map 容器

基本介绍

简介:

  • map 中所有元素都是 pair
  • pair 中第一个元素 key(键值),起到索引作用,第二个元素 value(实值)
  • 所有元素都会根据元素的键值自动排序

本质:

  • map / multimap 属性关联式容器,底层结构是用二叉树实现

优点:

  • 可以根据 key 值快速找到 value 值

map和multimap区别:

  • map 不允许容器中有重复的 key 值元素
  • multimap 允许容器中有重复的 key 值元素

构造和赋值

#include <iostream>
#include <map>
using namespace std;

void printMap(map<int, int> &m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ":" << (*it).second << ", ";
	}
	cout << endl;
}

void test()
{
	// 默认构造
	map<int, int> m;		// 创建map容器

	// 插入数据
	m.insert(pair<int, int>(4, 19));
	m.insert(pair<int, int>(1, 45));
	m.insert(pair<int, int>(3, 33));
	m.insert(pair<int, int>(2, 12));

	printMap(m);

	// 拷贝构造
	map<int, int> m2(m);
	printMap(m2);

	// 赋值
	map<int, int> m3;
	m3 = m2;
	printMap(m3);
}

int main()
{
	test();
}

大小和交换

#include <iostream>
#include <map>
using namespace std;

void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << (*it).first << ":" << (*it).second << ", ";
	}
	cout << endl;
}

void test()
{
	// 创建map容器
	map<int, int> m;

	// 插入数据
	m.insert(pair<int, int>(4, 19));
	m.insert(pair<int, int>(1, 45));
	m.insert(pair<int, int>(3, 33));
	m.insert(pair<int, int>(2, 12));

	if (m.empty())
	{
		cout << "m为空" << endl;
	}
	else
	{
		cout << "m不为空" << endl;
		cout << "m的大小:" << m.size() << endl;
	}

	map<int, int> m1;
	m1.insert(pair<int, int>(5, 29));
	m1.insert(pair<int, int>(3, 46));
	m1.insert(pair<int, int>(9, 13));

	cout << "交换前:" << endl;
	printMap(m);		// 1:45, 2:12, 3:33, 4:19,
	printMap(m1);		// 3:46, 5:29, 9:13,

	m.swap(m1);

	cout << "交换后:" << endl;
	printMap(m);		// 3:46, 5:29, 9:13,
	printMap(m1);		// 1:45, 2:12, 3:33, 4:19,
}

int main()
{
	test();
}

插入和删除

insert(elem)		// 在容器中插入元素
clear();			// 清除所有元素
erase(pos);			// 删除pos迭代器所指向的元素,返回下一个元素的迭代器
erase(beg, end);	// 删除区间[beg, end]的所有元素,返回下一个元素的迭代器
erase(key);			// 删除元素中值为key的元素

查找和统计

find(key);		// 查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key);		// 统计key元素个数

排序

map 容器默认排序规则为:按照key值进行"从小到大排序",掌握如何改变排序规则
利用仿函数,可以改变排序规则
#include <iostream>
#include <map>
using namespace std;


// 仿函数
class MyCompare
{
public:
	bool operator()(int v1, int v2)
	{
		// 降序排列
		return v1 > v2;
	}
};

void test()
{
	// 创建map容器
	map<int, int, MyCompare> m;

	// 插入数据
	m.insert(make_pair(4, 19));
	m.insert(make_pair(1, 45));
	m.insert(make_pair(3, 33));
	m.insert(make_pair(2, 12));

	// 输出容器中的数据
	for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key: " << (*it).first << " value: " << (*it).second << endl;
	}
}

int main()
{
	test();
}

函数对象 (仿函数)

#include <iostream>
#include <string>
using namespace std;

// 函数对象(又叫仿函数)
class MyAdd
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};

// 1. 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
void test1()
{
	MyAdd add;
	cout << add(10, 20) << endl;		// add() 实际上是对象调用()运算符进行重载,因为很像函数,所以也可以称之为"仿函数"
}



// 2. 函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint
{
public:
	void operator()(string text)
	{
		cout << text << endl;
		this->count++;
	}
	int count = 0;	// 内部自己的状态
};

void test2()
{
	MyPrint print;
	print("hello world");
	print("hello world");
	print("hello world");
	print("hello world");
	print("hello world");

	cout << "一共打印的次数:" << print.count << endl;
}

// 3. 函数对象可以作为参数传递
void doPrint(MyPrint& mp, string text)
{
	mp(text);
}

void test3()
{
	MyPrint print;
	doPrint(print, "Hello World");
}

int main()
{
	test1();
	test2();
	test3();
}

谓词

基本概念

  • 返回 bool 类型的仿函数称为谓词
  • 如果 operator() 接收一个参数,那么叫做一元谓词
  • 如果 operator() 接收两个参数,那么叫做二元谓词

具体内容

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 返回值类型是bool数据类型的仿函数称为谓词


// 一元谓词
class GreaterFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};

void test1()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	
	// 查找容器中有没有大于5的数字
	// GreaterFive() -- 匿名函数对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	if (it == v.end())
	{
		cout << "未找到" << endl;
	}
	else
	{
		cout << "找到了大于5的数字,它是:" << *it << endl;
	}
}


// 二元谓词
class MyCompare
{
public:
	bool operator()(int val1, int val2)
	{
		return val1 > val2;
	}
};

void test2()
{
	vector<int> v;
	v.push_back(20);
	v.push_back(50);
	v.push_back(30);
	v.push_back(40);
	v.push_back(10);

	sort(v.begin(), v.end());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	// 使用函数对象,改变算法策略,变为排序规则为从大到小
	sort(v.begin(), v.end(), MyCompare());		// MyCompare() -- 匿名函数对象
}

int main()
{
	test1();
	test2();
}

内建函数对象

基本介绍

概念:STL 内部建立了一些函数对象

分类:

  • 算术仿函数
  • 关系仿函数
  • 逻辑仿函数

用法:

  • 这些仿函数所产生的对象,用法和一般函数完全相同
  • 使用内建函数对象,需要引入头文件 #include <functional>

算术仿函数

#include <iostream>
#include <functional>	// 内建的函数对象头文件
using namespace std;

void test1()
{
	// 取反 仿函数
	negate<int> n;
	cout << n(20) << endl;

	// 加法 仿函数
	plus<int> p;
	cout << p(10, 20) << endl;
}

int main()
{
	test1();
}

关系仿函数

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>	// 内建的函数对象头文件
using namespace std;

class MyCompare
{
public:
	bool operator()(int val1, int val2)
	{
		return val1 > val2;
	}
};

void test1()
{
	vector<int> v;

	v.push_back(20);
	v.push_back(50);
	v.push_back(30);
	v.push_back(10);
	v.push_back(40);

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	// 降序
	// 方法1:使用自己写的规则【即:使用自己写的仿函数】
	sort(v.begin(), v.end(), MyCompare());		// MyCompare() -- 匿名函数对象

	// 方法2:使用内建仿函数【greater是"大于"关系的内建仿函数】
	sort(v.begin(), v.end(), greater<int>());
	
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

int main()
{
	test1();
}

逻辑仿函数

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>	// 内建的函数对象头文件
using namespace std;



void test1()
{
	vector<bool> v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);
	v.push_back(true);
	v.push_back(false);

	// 输出容器内容
	for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;


	vector<bool> v2;
	v2.resize(v.size());

	// 利用逻辑非		将容器v搬运到容器v2中,并执行取反操作
	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());


	// 输出容器内容
	for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

int main()
{
	test1();
}

STL常用算法简介

  • 算法主要是由头文件 组成
  • 是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等
  • 体积很小,只包括几个在序列上面进行简单数学运算的模板函数
  • 定义了一些模板类,用以声明函数对象

遍历算法

- for_each		// 遍历容器
- transform		// 搬运容器到另一个容器中

for_each

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 普通函数
void print(int val)
{
	cout << val << endl;
}

// 仿函数
class MyPrint
{
public:
	void operator()(int val)
	{
		cout << val << endl;
	}
};

void test()
{
	// 创建容器
	vector<int> v;

	// 添加数据
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	// 遍历数据
	for_each(v.begin(), v.end(), print);
	for_each(v.begin(), v.end(), MyPrint());		// MyPrint() -- 匿名函数对象
}

int main()
{
	test();
}

transform

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


class Transform
{
public:
	int operator()(int v)
	{
		v *= 10;
		return v;
	}
};

class MyPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test()
{
	// 创建原始容器
	vector<int> v;

	// 向原始容器中添加数据
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	// 查看原始容器中的内容
	for_each(v.begin(), v.end(), MyPrint());		// MyPrint() -- 匿名函数对象

	cout << endl;

	// 创建目标容器
	vector<int> vTarget;

	// 开辟好空间,准备存放数据
	vTarget.resize(v.size());

	// 将原始容器的每一个元素乘以10再放到目标容器中
	transform(v.begin(), v.end(), vTarget.begin(), Transform());	// Transform() -- 匿名函数对象

	// 输出目标容器的内容
	MyPrint print;
	for_each(vTarget.begin(), vTarget.end(), print);				// print -- 有名函数对象、或者就叫函数对象、或者对象
}

int main()
{
	test();
}

/*
	运行结果:
		0 1 2 3 4 5 6 7 8 9
		0 10 20 30 40 50 60 70 80 90
*/

查找算法

find			// 查找元素
find_if			// 按条件查找元素
adjacent_find	// 查找相邻重复元素
binary_search	// 二分法查找
count			// 统计元素个数
count_if		// 按照条件统计元素个数

排序算法

sort				// 对容器内元素进行排序
random_shuffle		 // 洗牌,指定范围内的元素随机调整次序
merge				// 容器元素合并,并存储到另一个容器中
reverse				// 反转指定范围的元素

拷贝和替换算法

copy		// 容器内指定范围的元素拷贝到另一容器中
replace		// 将容器内指定范围的旧元素修改为新元素
replace_if	// 将容器内指定范围满足条件的元素替换为新元素
swap		// 互换两个容器的元素

算术生成算法

使用时,请包含头文件 #include <numeric>

- accumulate	 // 计算容器元素累计总和
- fill			// 向容器中添加元素

集合算法

set_intersection		 // 求两个容器的交集
set_union				// 求两个容器的并集
set_difference			// 求两个容器的差集