STL-标准模板库

标准模板库(STL) 容器 阅读详情

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			// 求两个容器的差集
C++ - STL标准库 1.C++ STL标准库简介 长久以来,软件界一直希望建立一种可重复利用的东西,以及一种得以制造出”可重复运用的东西” 的方法,从函数(functions),类别(classes),函数库(function libraries),类别库(class libraries)、各种 组件,从模块化设计,到面向对象(object oriented ),为的就是复用性的提升。 复用性必须建立在某种标准之上。但是在许多环境下,就连软件开发最基本的数据结构(data structures) 和算法(algori 阅读详情

相关推荐

C++标准模板库(STL)

但如果定义的是万能头,则可以直接忽略//定义:int 数组名;int a;//输入:while(cin>>数组名){数组名.push_back(a);

@Ysjt丨深的博客 喜欢就留下哦 1479

面向对象和C++基础—标准模板库(STL)篇

面向对象和C++基础—标准模板库(STL)篇

Voltline的博客 1466

STL(标准模板库)理论基础

/STL 中的容器 算法 迭代器//STL 中的标准容器之一 :动态数组//vector 容器提供的插入数据的方法//迭代器//vector 容器提供了 begin()方法 返回指向第一个元素的迭代器//vector 容器提供了 end()方法 返回指向最后一个元素下一个位置的迭代器//通过迭代器遍历= pEnd){pStart++;

程序员_小兵 995

标准模板库STL

向量(vector):类似数组(内部是线性存储)支持下标访问,在尾部添加和删除元素效率高,中间执行添加删除操作可以,但效率很低。双端队列( deque ) : 支持下标访问(头尾两端都可添加/删除操作)。列表(list):在任何位置添加和删除操作都很方便,不支持下标访问。堆栈(stack):支持在一端存储和提取元素。队列(queue):支持从前端提取,后端压入元素。优先队列(priority_queue):类似队列,但所提取的是具有最高优先级的元素(默认大者优先)。映射(map)

qq_37346140的博客 1139

STL(标准模板库)

概念: STL:标准模板库,是C++标准库的重要组成部分 由概念便可以知道,STL中的所有数据结构都是以模板的方式创建的 LIST--container: list节点: list节点是一个双向指针,实质是一个模板结构体 template<class T> struct _list_node { typedef void* void_pointer; void_pointer prev;//previous void_pointer next;

m0_60274660的博客 2万+

C++ STL 标准模板库介绍与入门

C++ STL 标准模板库概述与入门

dvlinker的技术专栏 2万+

STL 标准模板库

STL 标准模板库 文章目录STL 标准模板库1了解标准模板库STL2标准模板库STL之vector3标准模板库STL之list4标准模板库STL之string5标准模板库STL之map 1了解标准模板库STL STL: 标准模板库 STL, standard template library 标准模板库,一般支持C++的编译器都带了STL的支持。里面 提供了大量的函数模板(通用算法...

爱吃蛋炒饭蜗牛君的博客 356

【STL详解】STL标准模板库入门 | STL版本 | STL六大组件 | STL优点 | 常用STL容器vector、list和map | STL算法函数 | STL使用异常原因分析与总结

本文详细介绍STL标准模板库相关的内容,包括STL版本、STL六大组件、STL优点、常用的STL容器vector、list与map、提升效率的STL算法函数的使用、STL使用异常常见原因分析与总结等,以供大家参考。

dvlinker的技术专栏 2万+

C++ 标准模板库 STL 概述

C++ 标准模板库 STL 概述 泛型程序设计 C++ 的特点: ​ C++ 的核心优势之一就是便于软件重用,而软件的重用在 C++ 中主要体现在以下两个方面: 面向对象的思想:继承、多态和标准类库 泛型程序设计的思想:模板机制和标准模板库 STL 泛型程序设计: ​ 泛型程序设计通俗地讲就是使用模板的程序设计方法。泛型程序设计中将一些常用的数据结构(例如链表、数组和二叉树等)和算法(例如排序和查找等)写成模板,这样在后续的使用中不管数据结构中存放的是什么数据对象,算法应用于什么类型的数据对象,都不需要

王清欢的博客 9663

STM32F103四位数码管动态显示实战:从硬件连接到代码调试(附Proteus仿真)

本文详细介绍了STM32F103驱动四位数码管的动态显示技术,从硬件连接到代码调试的全过程。内容包括共阴/共阳数码管的区别、GPIO配置、动态显示原理及优化方法,并附有Proteus仿真验证。通过实战案例,帮助开发者快速掌握STM32数码管动态显示的核心技术。

weixin_29168393的博客 469

Zlib1.2.11源码编译(Win10+VS2019)

下载 下载网址: zlib Home Site 得到文件: 解压缩到“D:\SourceCodes\zlib-1.2.11” 使用CMake配置、生成并打开项目 将CMakeLists.txt拖入CMake,配置(Configure): 生成(Generate) 打开项目(Open Project),CMake调用VS2019打开项目 生成debug版本 构建项目ALL_BUILD。成功生成debug版本 在“D:\Sourc...

Alexabc3000的专栏 1892

C++中的STL标准模板库和string

大致介绍了STL六大组件的基础构成,以及string类的功能及模拟实现

2301_79976271的博客 1060

可微编程:当深度学习遇见物理定律,重塑科学计算新范式

本文探讨了可微编程如何将深度学习与物理定律相结合,重塑科学计算范式。通过自动微分技术,它将物理方程融入可微计算图,使模型在数据驱动的同时遵守物理约束。文章以神经常微分方程为例,阐述了其在连续系统建模、科学模拟器优化等领域的应用,并分析了当前面临的挑战与最佳实践路径。

weixin_29056145的博客 134

C++ 标准模板库 (STL)

C++ 标准模板库(STL)是一组模板类和函数,用于实现常见的数据结构和算法,如列表、堆栈、数组、排序和搜索等。STL 由 Alexander Stepanov 设计,并在 C++ 98 中成为标准。它包含四个主要组件:容器、算法、迭代器和函数。容器用于存储数据,分为序列容器、容器适配器、关联容器和无序关联容器。算法提供对数据的操作,如排序和搜索。迭代器用于遍历容器,而函数则用于执行特定操作。STL 的优势在于其通用性和可重用性,减少了代码重复和内存管理问题。然而,STL 也存在性能开销和调试复杂性等限制。

SEO_juper的博客 993

别再手动下单了!用Python+EasyTrader+同花顺,5分钟搞定你的第一个自动化交易机器人

本文详细介绍了如何使用Python和EasyTrader结合同花顺客户端快速构建自动化交易机器人。从环境配置到实战脚本编写,涵盖自动打新、条件单、跟单策略等核心功能,并分享性能优化与风险控制技巧,帮助投资者高效实现自动化交易。

weixin_30381317的博客 398

Anomalib实战指南:从零开始构建自定义异常检测数据集

本文提供了一份详细的Anomalib实战指南,指导用户从零开始构建自定义异常检测数据集。文章深入解析了数据准备的核心步骤、目录结构规范,并对比了PatchCore与FastFlow等关键模型的适用场景。通过清晰的代码示例,手把手演示了环境配置、模型训练与推理评估的全流程,旨在帮助开发者快速掌握这一工业视觉异常检测利器,有效解决实际生产中的缺陷识别难题。

weixin_29054245的博客 643

STL标准模板库

STL标准模板库 一。概述 C++内置的标准模板库STL可以分为以下6大类: 1.容器 2.迭代器 3.空间分配器 4.适配器 5.算法 6.仿函数 1.容器: 概念:用来管理一组元素 分类: 序列式容器(Sequence containers)       每个元素都有固定位置--取决于插入时机和地点,和元素值无关。       vector、deque、list   关联式容器(Associa...

糖炒栗子的博客 5768

nvidia系列教程-AGX-Orin基础环境搭建

NVIDIA Jetson AGX Orin 是一款功能强大的嵌入式AI平台,专为需要高性能和低功耗的边缘计算应用设计。无论是自动驾驶、机器人,还是智能监控系统,Jetson AGX Orin 都能为这些应用提供强大的计算能力。本篇博客将为大家详细介绍如何在AGX Orin(32GB)上搭建基础开发环境,包括系统安装、CUDA和cuDNN的配置等,帮助你快速上手这个强大的平台。架构: 搭载 56 个 Tensor Core 的 1792 核 NVIDIA Ampere c GPUCUDA Cores。

flypig has a dream! 2796

【C++】STL标准模板库

/自定义数据类型pulic:mAge = age;//存放对象//创建数据it!= v.end();it++)//vector容器存储指针//创建数据//指针指向地址it!= v.end();it++)//二级指针int main()test01();test02();

weixin_43490759的博客 780

YOLOv11【第二章:核心模块进阶篇·第28节】DynamicHead动态检测头设计!

🏆 本文收录于专栏 《YOLOv11实战:从入门到深度优化》。本专栏围绕 YOLOv11 的改进、训练、部署与工程优化 展开,系统梳理并复现当前主流的 YOLOv11 实战案例与优化方案,内容目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。

**My Coding Family** 1万+

华为OD机试真题 新系统 2026-06-10 C++ 实现【设备重排SN】

通信设备SN一般是包含:字母、数字,用'-'(破折号)进行分组分割,例如:8F-3T-1G-2n是一个有效的SN地址。 现在要对已经存在的SN 按照新的规则进行重排:

MISAYAONE的博客 129

STL(标准模板库)的简单使用

STL(标准模板库)的简单使用 一. STL简介       STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来 二. 算法    &...

qq_38937025的博客 1146

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

STL标准模板库(一)

这下子我们一口气将STL中常用的一大部分讲完了,请先缓一缓,自己去写写代码,多多记忆,这样才能将收益最大化。等下一篇,我们将剩余的stack,queue,priority_queue也一次性讲完!最后,本篇文章是作者自己学习过后自行总结而成,可能会有些缺漏,我就在此,请看官们赐教!!!!!!!

Ryan_hsMax的博客 2780

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【C++】STL 标准模板库

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。

一点一点变好 801

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

<C++>初识STL —— 标准模板库

目录STL的出现背景STL基本概念STL六大组件初识容器算法迭代器vector容器的初次使用存放内置数据类型存放自定义数据类型vector容器的嵌套使用 运行效果✨总结 迭代器种类: 常用的迭代器种类为双向迭代器,和随机访问迭代器。 存放自定义数据类型 vector容器的嵌套使用 容器相当于一个数组,那么数组嵌套数组不就是二维数组吗,我们来测试一下。 运行效果 那么到这里初识STL就结束了,跟着这篇博客学习可以了解ST....

叶落秋白的博客 1823
上一篇: c++补充
下一篇: C++多线程编程
code_stream
博客等级 码龄4年 1238粉丝 169原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值