doc/docs/CPlusPlus-main/29_C++的STL.md
sairate fa9377e4ae docs(book): 添加现代 C++教程及相关代码
- 新增现代 C++ 教程的 Preface 章节,包括英文和中文版本
- 添加 C++ Primer 练习代码
- 新增 Learn C++ 教程的 C++ 开发简介章节
- 添加头文件解析文档
- 更新 mkdocs.yml,包含新教程的目录结构
- 修改项目设置,使用 Python 3.10环境
2025-07-08 09:52:45 +08:00

4373 lines
90 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# C++的STL
# 1. STL
## 1.1 STL诞生
① 长久以来,软件界一直希望建立一种可重复利用的东西。
② C++的面向对象和泛型编程思想,目的就是复用性的提升。
③ 大多数情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作。
④ 为了建立数据结构和算法的一套标准诞生了STL。
## 1.2 STL基本概念
① STL(Standard Template Library标准模板库)
② STL 从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
③ 容器和算法之间通过迭代器进行无缝连接。
④ STL 几乎所有的代码都采用了模板类或者模板函数。
## 1.3 STL六大组件
① STL大体分为六大组件分别是容器、算法、迭代器、仿函数、适配器(配接器)、空间配准器。
1. 容器各种数据结构如vector、list、deque、set、map等用来存放数据。
2. 算法各种常用的算法如sort、find、copy、for_each等。
3. 迭代器:扮演了容器与算法之间的胶合剂。
4. 仿函数:行为类似函数,可作为算法的某种策略。
5. 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
6. 空间配置器:负责空间的配置与管理。
## 1.4 STL容器
① 容器:置物之所也。
② STL容器就是将运用最广泛的一些数据结构实现出来。
③ 常用的数据结构:数组、链表、树、栈、队列、集合、映射表 等。
④ 这些容器分为序列式容器和关联式容器两种:
1. 序列式容器:强调值的排序,序列式容器中每个元素均有固定的位置(怎么往里放,位置就固定了)。
2. 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系(不是怎么往里放就怎么排序,它会自动进行排序,然后固定位置)。
## 1.5 STL算法
① 算法:问题之解法
② 有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫算法(Algorithms)
③ 算法分为:质变算法和非质变算法。
1. 质变算法:是指运算过程中会更改区间内的元素内容,例如拷贝、替换、删除等等。
2. 非质变算法:是指运算过程中不会更改区间内的元素,例如查找、计数、遍历、寻找极值等等。
## 1.6 STL迭代器
① 迭代器:容器和算法之间粘合剂。
② 提供一种方法,使之能够依序寻找某个容器所含的各个元素,而无需暴露容器的内部表示方式。
③ 每个容器都有自己专属的迭代器。
④ 迭代器使用非常类似于指针,可以先理解迭代器为指针。
![image.png](29_C++的STL_files/image.png)
## 1.7 STLvector存放内置数据类型
① STL中最常用的容器为Vector可以理解为数组。
```python
#include <iostream>
using namespace std;
#include<vector> //STL中每个容器要使用都要包含对应的头文件
#include<algorithm> //这是标准算法的头文件
//vector容器存放内置数据类型
void myPrint(int val)
{
cout << val << endl;
}
void test01()
{
//创建一个vector容器数组
vector<int> v; //容器中的数据类型为int
//向容器中插入数据
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//通过迭代器访问容器中的数据
vector<int>::iterator itBegin = v.begin(); //起始迭代器itBegin 指向容器中第一个元素的位置
vector<int>::iterator itEnd = v.end(); // 结束迭代器itEnd 指向容器中最后一个元素的下一个位置
//第一种遍历方式
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); //要用STL中的标准算法就要提供标准算法的头文件
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 10
- 20
- 30
- 40
- 10
- 20
- 30
- 40
- 10
- 20
- 30
- 40
- 请按任意键继续. . .
## 1.8 STL存放自定义数据类型
```python
#include <iostream>
using namespace std;
#include<string>
#include<vector> //STL中每个容器要使用都要包含对应的头文件
//vector容器中存放自定义数据类型
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
vector<Person>v; //容器中放的是Person的数据类型
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; //<>是什么类型*it就是什么类型
//第二种拿到属性的方法由于已知it是个指针所以也可以通过it->m_Name拿到属性
cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
}
}
//存放自定义数据类型 指针
void test02()
{
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()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 姓名aaa 年龄10
- 姓名aaa 年龄10
- 姓名bbb 年龄20
- 姓名bbb 年龄20
- 姓名ccc 年龄30
- 姓名ccc 年龄30
- 姓名ddd 年龄40
- 姓名ddd 年龄40
- 姓名eee 年龄50
- 姓名eee 年龄50
- 姓名aaa 年龄10
- 姓名bbb 年龄20
- 姓名ccc 年龄30
- 姓名ddd 年龄40
- 姓名eee 年龄50
- 请按任意键继续. . .
## 1.9 STL容器嵌套容器
```python
#include <iostream>
using namespace std;
#include<vector>
//容器嵌套容器
void test01()
{
vector<vector<int>>v;
//创建小容器
vector<int>v1;
vector<int>v2;
vector<int>v3;
vector<int>v4;
//向4个小容器中添加数据
for (int i = 0; i < 4; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
//将小容器插入到大容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
//通过大容器把所有数据遍历一遍
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
{
//(*it) 是一个容器 vector<int>
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 1 2 3 4
- 2 3 4 5
- 3 4 5 6
- 4 5 6 7
请按任意键继续. . .
# 2. string容器
## 2.1 简介
① string是C++风格的字符串而string本质上是一个类。
② string 和 char * 区别:
1. char * 是一个指针
2. string 是一个类,类内部封装了 char *管理这个字符串是一个char型容器。
③ string特点
1. string类内部封装了很多成员方法。
2. 例如查找find拷贝copy删除delete替换replace插入insert。
3. string管理char * 所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责。
## 2.2 构造函数
① string构造函数原型
1. string(); // 创建一个空的字符串 例如string str;
2. string(const char * s); // 使用字符串s初始化
3. string(const string & str); // 使用一个string对象初始化另一个string对象
4. string(int n,char c); //使用n个字符c初始化
② string的多种构造方式没有可比性灵活使用即可。
```python
#include <iostream>
using namespace std;
#include<string>
//string的构造函数
/*
1. string(); // 创建一个空的字符串 例如string str;
2. string(const char* s); // 使用字符串s初始化
3. string(const string & str); // 使用一个string对象初始化另一个string对象
4. string(int n, char c); //使用n个字符c初始化
*/
void test01()
{
string s1; //默认构造就是空字符串
cout << "s1 = " << s1 << endl;
const char* str = "hello world"; //使用字符串s初始化
string s2(str);
cout << "s2 = " << s2 << endl;
string s3(s2);
cout << "s3 = " << s3 << endl;
string s4(10, 'a');
cout << "s4 = " << s4 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- s1 =
- s2 = hello world
- s3 = hello world
- s4 = aaaaaaaaaa
- 请按任意键继续. . .
## 2.3 赋值操作
① 给string字符串进行赋值。
② 赋值的函数原型:
1. string& operator=(const char* s); //char * 类型字符串赋值给当前的字符串
2. string& operator=(const strinng &s); //把字符串s赋给当前的字符串
3. string& operator=(char c); //字符赋值给当前的字符串
4. string& assign(const char *s); //把字符串s赋给当前的字符串
5. string& assign(const char *s,int n); //把字符串s的前n个字符赋给当前的字符串
6. string& assign(const string &s); //把字符串s赋给当前字符串
7. string& assign(int n, char c); //用n个字符c赋给当前字符串
③ string的赋值方式很多operator=这种方式是比较常用的。
```python
#include <iostream>
using namespace std;
#include<string>
//string赋值操作
/*
1. string& operator=(const char* s); //char * 类型字符串赋值给当前的字符串
2. string& operator=(const string &s); //把字符串s赋给当前的字符串
3. string& operator=(char c); //字符赋值给当前的字符串
4. string& assign(const char *s); //把字符串s赋给当前的字符串
5. string& assign(const char *s,int n); //把字符串s的前n个字符赋给当前的字符串
6. string& assign(const string &s); //把字符串s赋给当前字符串
7. string& assign(int n, char c); //用n个字符c赋给当前字符串
*/
void test01()
{
string str1;
str1 = "hello world"; //第一种等号方式
cout << "str1 = " << str1 << endl;
string str2;
str2 = str1; //第二种等号方式
cout << "str2 = " << str2 << endl;
string str3;
str3 = 'a'; //第三种等号方式
cout << "str3 = " << str3 << endl;
string str4;
str4.assign("hello C++"); //第一种assign方式
cout << "str4 = " << str4 << endl;
string str5;
str5.assign("hello C++",5); //第二种assign方式取字符串"hello C++"中的前五个字符赋值给str5
cout << "str5 = " << str5 << endl;
string str6;
str6.assign(str5); //第三种assign方式
cout << "str6 = " << str6 << endl;
string str7;
str7.assign(10,'w'); //第四种assign方式
cout << "str7 = " << str7 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- str1 = hello world
- str2 = hello world
- str3 = a
- str4 = hello C++
- str5 = hello
- str6 = hello
- str7 = wwwwwwwwww
- 请按任意键继续. . .
## 2.4 字符串拼接
① 实现在字符串末尾拼接字符串。
② 函数原型:
1. string& operator+=(const char* str); //重载+=操作符
2. string& operator+=(const char c); //重载+=操作符
3. string& operator+=(const string& str); //重载+=操作符
4. string& append+=(const char* s); //把字符串s连接到当前字符串结尾
5. string& append+=(const char* s, int n); //把字符串s的前n个字符连接到当前字符串结尾
6. string& append+=(const string &s); //同operator+=(const string& str)
7. string& append+=(const char &s, int pos, int n); //字符串s从pos开始的n个字符连接到字符串结尾
```python
#include <iostream>
using namespace std;
#include<string>
//string赋值操作
/*
1. string& operator+=(const char* str); //重载+=操作符
2. string& operator+=(const char c); //重载+=操作符
3. string& operator+=(const string& str); //重载+=操作符
4. string& append+=(const char* s); //把字符串s连接到当前字符串结尾
5. string& append+=(const char* s, int n); //把字符串s的前n个字符连接到当前字符串结尾
6. string& append+=(const string &s); //同operator+=(const string& str)
7. string& append+=(const char &s, int pos, int n); //字符串s从pos开始的n个字符连接到字符串结尾
*/
void test01()
{
string str1 = "我"; //字符串初始化
str1 += "爱玩游戏";
cout << "str1 = " << str1 << endl;
str1 += ':'; //追加一个字符
cout << "str1 = " << str1 << endl;
string str2 = " LOL DNF";
str1 += str2; //追加字符串
cout << "str1 = " << str1 << endl;
string str3 = "I";
str3.append(" love ");
cout << "str3 = " << str3 << endl;
str3.append("game abcde ",4); //只把字符串的前4个拼接过去
cout << "str3 = " << str3 << endl;
str3.append(str2);
cout << "str3 = " << str3 << endl;
str3.append(str2,0,4); //只截取到LoL参数2表示从哪个位置开始截取参数3表示截取字符个数
cout << "str3 = " << str3 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- str1 = 我爱玩游戏
- str1 = 我爱玩游戏:
- str1 = 我爱玩游戏: LOL DNF
- str3 = I love
- str3 = I love game
- str3 = I love game LOL DNF
- str3 = I love game LOL DNF LOL
- 请按任意键继续. . .
## 2.5 字符串查找和替换
① 查找:查找指定字符串是否存在。
② 替换:在指定的位置替换字符串。
③ 函数原型:
//查找str第一次出现位置从pos开始查找
1. int find(const string& str, int pos = 0) const;
// 查找s第一次出现位置从pos开始查找
2. int find(const char* s, int pos = 0) const;
//从pos位置查找s的前n个字符第一次位置
3. int find(const char* s, int pos, int n) const;
//查找字符c第一次出现位置
4. int find(const char c, int pos = 0) const;
//查找str最后一次位置从pos开始查找
5. int rfind(const string& str, int pos = npos) const;
//查找s最后一次出现位置从pos开始查找
6. int rfind(const char* s, int pos = npos) const;
//从pos查找s的前n个字符最后一次位置
7. int rfind(const char* s, int pos, int n) const;
//查找字符c最后一次出现位置
8. int rfind(const char c, int pos = 0) const;
//替换从pos开始n个字符为字符串str
9. string& replace(int pos, int n, const string& str) const;
//替换从pos开始的n个字符为s
10. string& replace(int pos, int n, const string* s) const;
④ find查找是从左往右rfind从右往左。
⑤ find找到字符串后返回查找的第一个字符位置找不到返回-1。
⑥ replace在替换时要知道从哪个位置起多少个字符替换成什么样的字符串。
```python
#include <iostream>
using namespace std;
#include<string>
//string查找和替换
/*
//查找str第一次出现位置从pos开始查找
1. int find(const string& str, int pos = 0) const;
// 查找s第一次出现位置从pos开始查找
2. int find(const char* s, int pos = 0) const;
//从pos位置查找s的前n个字符第一次位置
3. int find(const char* s, int pos, int n) const;
//查找字符c第一次出现位置
4. int find(const char c, int pos = 0) const;
//查找str最后一次位置从pos开始查找
5. int rfind(const string& str, int pos = npos) const;
//查找s最后一次出现位置从pos开始查找
6. int rfind(const char* s, int pos = npos) const;
//从pos查找s的前n个字符最后一次位置
7. int rfind(const char* s, int pos, int n) const;
//查找字符c最后一次出现位置
8. int rfind(const char c, int pos = 0) const;
//替换从pos开始n个字符为字符串str
9. string& replace(int pos, int n, const string& str) const;
//替换从pos开始的n个字符为s
10. string& replace(int pos, int n, const string* s) const;
*/
//1查找
void test01()
{
string str1 = "abcdefgde";
int pos = str1.find("de"); //从零开始索引返回值为d出现的位置"3"若找不到子字符串就返回-1
if (pos == -1)
{
cout << "未找到字符串 pos = " << pos << endl;
}
else
{
cout << "找到字符串 pos = " << pos << endl;
}
//rfind
pos = str1.rfind("de"); //rfind是从右往左查找find是从左往右查找
cout << "pos=" << pos << endl;
}
void test02()
{
string str1 = "abcdefg";
str1.replace(1, 3, "1111"); // "1" 号位置起"1111"有四个字符所以变为4个字符替换成 "1111"而不是出现3个字符替换成"111"
cout << "str1= " << str1 << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 找到字符串 pos = 3
- pos=7
- str1= a1111efg
- 请按任意键继续. . .
## 2.6 字符串比较
① 功能描述:字符串之间比较。
② 比较方式字符串比较是按字符的ASCII码进行对比。
1. $=$ 返回 0
2. $>$ 返回 1
3. $<$ 返回 -1
③ 函数原型:
1. int compare(const string & s) const; //与字符串s比较
2. int compare(const char * s) const; //与字符串s比较
```python
#include <iostream>
using namespace std;
#include<string>
//字符串比较
//1查找
void test01()
{
string str1 = "hello";
string str2 = "hello";
//compar常用于比较两个字符串相等或不相等判断谁大谁小的意义并不是很大
if (str1.compare(str2) == 0)
{
cout << "str1 等于 str2" << endl;
}
else if (str1.compare(str2) > 0)
{
cout << "str1 大于 str2" << endl;
}
else
{
cout << "str1 小于 str2" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- str1 等于 str2
- 请按任意键继续. . .
## 2.7 字符串存取
① string中单个字符存取方式有两种
1. char& operator[](int n); //通过[]方式取字符
2. char& at(int n); //通过at方式取字符
```python
#include <iostream>
using namespace std;
#include<string>
//string 字符存取
void test01()
{
string str = "hello";
cout << "str= " << str << endl;
//1通过[]访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str[i] << " ";
}
cout << endl; //换行符
//2通过at方式访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str.at(i) << " ";
}
cout << endl;
//修改单个字符
str[0] = 'x';
cout << "str= " << str << endl;
str.at(1) = 'x';
cout << "str= " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- str= hello
- h e l l o
- h e l l o
- str= xello
- str= xxllo
- 请按任意键继续. . .
## 2.8 字符串插入和删除
① 功能描述对string字符串进行插入和删除字符操作。
② 函数原型:
1. string& insert(int pos, const char * s); // 插入字符串
2. string& insert(int pos, const string& str); //插入字符串
3. string& insert(int pos, int n, char c); //在指定位置插入n个字符c
4. string& erase(int pos, int n = npos); //删除从Pos开始的n个字符
③ 插入和删除的起始下标都是从0开始。
```python
#include <iostream>
using namespace std;
#include<string>
//字符串 插入和删除
void test01()
{
string str = "hello";
//插入
str.insert(1, "111");
//hello
cout << "str = " << str << endl;
//删除
str.erase(1, 3); //从第1个位置起删3个
cout << "str = " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- str = h111ello
- str = hello
- 请按任意键继续. . .
## 2.9 子串获取
① 功能描述:从字符串中获取想要的子串。
② 函数原型:
1. string substr(int pos = 0, int n = npos) const; //返回由pos开始的n个字组成的字符串。
③ 灵活的运用求子串功能,可以在实际开发中获取有效的信息。
```python
#include <iostream>
using namespace std;
#include<string>
//string 求子串
void test01()
{
string str = "abcdef";
string subStr = str.substr(1, 3);
cout << "subStr = " << subStr << endl;
}
//实用操作
void test02()
{
string email = "zhangsan@sina.com";
//从邮件地址中 获取 用户名称
int pos = email.find("@");
cout << pos << endl;
string usrName = email.substr(0, pos);
cout << usrName << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- subStr = bcd
- 8
- zhangsan
- 请按任意键继续. . .
# 3.vector容器
## 3.1 简介
① vector数据结构和数组非常相似也称为单端数组。
② vector与普通数组区别不同之处在于数组是静态空间而vector可以动态扩展。
③ 动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。
④ vector容器的迭代器是支持随机访问的迭代器。
![image.png](29_C++的STL_files/image.png)
## 3.2 构造函数
① 功能描述创建vector容器
② 函数原型:
1. vector<T> v;
2. vector(v.begin(), v,end()); //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。
3. vector(n, elem); //构造函数将n个elem拷贝给本身
4. vector(const vector &vec); //拷贝构造函数
```python
#include <iostream>
using namespace std;
#include<vector>
void printVector(vector<int>&v) //各种容器的接口v1容器传进去就打印v1容器
{
for (vector<int>::iterator it = v.begin(); it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器构造
void test01()
{
vector<int> v1; //默认构造 无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//通过区间方式进行构造
vector<int>v2(v1.begin(), v1.end()); //把v1.begin()-v1.end()区间内数给v2
printVector(v2);
//n个elem方式构造
vector<int>v3(10, 100); //这是10个100不是100个10
printVector(v3);
//拷贝构造
vector<int>v4(v3);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8 9
- 100 100 100 100 100 100 100 100 100 100
- 100 100 100 100 100 100 100 100 100 100
- 请按任意键继续. . .
## 3.3 赋值操作
① 功能描述给vector容器进行赋值。
② 函数原型:
1. vector& operator=(const vector &vec); //重载等号操作符。
2. assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身。
3. assign(n,elem); //将n个elem拷贝赋值给本身。
③ vector赋值方式比较简单使用operator=或者assign都可以。
```python
#include <iostream>
using namespace std;
#include<vector>
//vector赋值
void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << "";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//赋值 operator=
vector<int>v2;
v2 = v1;
printVector(v2);
//assign
vector<int>v3;
v3.assign(v1.begin(), v1.end()); //提供两个迭代器两个迭代器区间中的元素都赋值给vector容器区间为前闭后开
printVector(v3);
//n个elem方式赋值
vector<int>v4;
v4.assign(10, 100);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0123456789
- 0123456789
- 0123456789
- 100100100100100100100100100100
- 请按任意键继续. . .
## 3.4 容量和大小
① 功能描述对vector容器的容量和大小操作。
② 函数原型:
//判断容器是否为空
1. empy();
//容器的容量
2. capacity();
//返回容器中元素的个数
3. size();
//重新指定容器的长度为num若容器变长则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
4. resize(int num);
//重新指定容器的长度为num若容器变成则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
5. resize(int num, elem);
③ vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。
④ vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意,这里的“更多”并不是 1 个。换句话说,当 vector 容器的大小和容量相等时如果再向其添加或者插入一个元素vector 往往会申请多个存储空间,而不仅仅只申请 1 个。
⑤ 一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。
```python
#include <iostream>
using namespace std;
#include<vector>
//vector容器的容量和大小操作
void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << "";
}
cout << endl;
}
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
if (v1.empty()) //为真 代表容器为空
{
cout << "v1为空" << endl;
}
else
{
cout << "v1不为空" << endl;
cout << "capacity容量" << v1.capacity() <<endl;
cout << "v1的大小为" << v1.size() << endl;
//重新指定大小
v1.resize(15); //如果重新指定的比原来长了默认用0填充新的位置
printVector(v1);
v1.resize(20,100); //利用重载版本参数2可以指定默认填充值
printVector(v1);
v1.resize(5); //如果重新指定的比原来短了超出的部分会删除掉
printVector(v1);
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0123456789
- v1不为空
- capacity容量13
- v1的大小为10
- 012345678900000
- 012345678900000100100100100100
- 01234
- 请按任意键继续. . .
## 3.5 插入删除
① 功能描述对vector容器进行插入、删除操作。
② 函数原型:
1. push_back(ele); //尾部插入元素ele
2. pop__back(); //删除最后一个元素
3. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
4. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素
5. erase(const_iterator pos); //删除迭代器指向的元素
6. erase(cons_titerator start, const_iterator end); //删除迭代器从start到end之间的元素
7. clear(); //删除容器中所有元素
```python
#include <iostream>
using namespace std;
#include<vector>
void printVector(vector<int>v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
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);
//尾删
v1.pop_back();
printVector(v1);
//插入 参数是迭代器
v1.insert(v1.begin(), 100);
printVector(v1);
//删除 参数也是迭代器
v1.insert(v1.begin(),2,999);
printVector(v1);
//删除
v1.erase(v1.begin());
printVector(v1);
//清空 方式一
v1.erase(v1.begin(), v1.end());
printVector(v1);
//清空 方式二
v1.clear();
printVector(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40 50
- 10 20 30 40
- 100 10 20 30 40
- 999 999 100 10 20 30 40
- 999 100 10 20 30 40
-
-
- 请按任意键继续. . .
## 3.6 数据存取
① 功能描述对vector中的数据存取操作。
② 函数原型:
1. at(int idx); ///返回索引idx所指的数据。
2. operator[]; //返回索引idx所指的数据。
3. front(); //返回容器中第一个数据元素
4. back(); //返回容器中最后一个数据元素
③ 除了用迭代器获取vector容器中元素[]和at也可以。
④ front返回容器第一个元素。
⑤ back返回容器最后一个元素。
```python
#include <iostream>
using namespace std;
#include<vector>
void printVector(vector<int>v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
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;
//利用at方式访问元素
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
//获取第一个元素
cout << "第一个元素为:" << v1.front() << endl;
//获取最后一个元素
cout << "最后一个元素为:" << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8 9
- 第一个元素为0
- 最后一个元素为9
- 请按任意键继续. . .
## 3.7 互换容器
① 功能描述:实现两个容器内元素进行互换。
② 函数原型swao(vec); //将vec与本身的元素互换
③ swap可以使两个容器互换可以达到实用的收缩内存效果。
```python
#include <iostream>
using namespace std;
#include<vector>
//vector容器互换
void printVector(vector<int>v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//1基本使用
void test01()
{
cout << "交换前:" << endl;
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector<int>v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//2实际用途
//巧用swap可以收缩内存空间
void test02()
{
vector<int>v;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}
cout << "v的容量为" << v.capacity() << endl;
cout << "v的大小为" << v.size() << endl;
v.resize(3); //重新指定大小
cout << "v的容量为" << v.capacity() << endl; //resize操作容量并没有变多余的容量浪费了
cout << "v的大小为" << v.size() << endl;
//巧用swap收缩内存
vector<int>(v).swap(v); //vector<int>(v)创建了一个为匿名对象会按v的大小初始化这个匿名对象容器的大小
//.swap(v)会对匿名对象容器与原容器做一个交换则原容器的指针指向匿名对象的容器匿名对象的容器的指针改为指向原容器
// 系统运行完创建匿名函数这一句语句后对匿名对象的指针(即地址内存)进行回收
cout << "v的容量为" << v.capacity() << endl;
cout << "v的大小为" << v.size() << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 交换前:
- 0 1 2 3 4 5 6 7 8 9
- 10 9 8 7 6 5 4 3 2 1
- 交换后:
- 10 9 8 7 6 5 4 3 2 1
- 0 1 2 3 4 5 6 7 8 9
- v的容量为138255
- v的大小为100000
- v的容量为138255
- v的大小为3
- v的容量为3
- v的大小为3
- 请按任意键继续. . .
## 3.8 预留空间
① 功能描述减少vector在动态扩展容量时的扩展次数。
② 函数原型:
1. reserve(int len); //容器预留len个元素长度预留位置不初始化元素不可访问。
```python
#include <iostream>
using namespace std;
#include<vector>
//vector容器 预留空间
void test01()
{
vector<int>v;
int num = 0; //统计开辟次数
int* p = NULL;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
if (p != &v[0]) //一开始指针不指向容量首地址所以让指针指向容量首地址开辟内存次数加1
{
p = &v[0];
num++; //由于容量不够会再次开辟一段容量更大的内存空间原小容量的内存空间被释放
}
}
cout << "num" << num << endl;
}
void test02()
{
vector<int>v;
//预留空间
v.reserve(100000);
int num = 0; //统计开辟次数
int* p = NULL;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
if (p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num" << num << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- num30
- num1
- 请按任意键继续. . .
# 4. deque容器
## 4.1 简介
① 功能:双端数组,可以对头端进行插入删除操作,也可以对尾端进行插入和删除操作。
② deque与vector区别
1. vector对于头部的插入效率低数据量越大效率越低例如头部后有十万个数据则往头部插入一个数据时十万个数据都需要往后挪一挪才能在头部插入数据。
2. deque相对而言对头部的插入删除速度会比vector快
3. vector访问元素时的速度会比deque快这和两者内部实现有关。
![image.png](29_C++的STL_files/image.png)
③ deque内部工作原理
1. deque内部有个中控器维护每段缓冲区中的内容缓冲区中存放真实数据。
2. 中控器维护的是每个缓冲区的地址使得使用deque时像一片连续的内存空间。
![image.png](29_C++的STL_files/image.png)
④ deque容器的迭代器也是支持随机访问的。
## 4.2 构造函数
① 功能描述deque容器构造。
② 函数原型:
1. deque<T>deqT; //默认构造形式
2. 构造函数将[beg,end)区间中的元素拷贝给本身。
3. deque(n,elem); //构造函数将n个elem拷贝给本身
4. deque(const deque &deq); //拷贝构造函数
③ deque荣哪个器和vector容器的构造方式几乎一致灵活使用即可。
```python
#include <iostream>
using namespace std;
#include<deque>
//deque容器 构造函数
void printDeuque(const deque<int>& d) //const 防止进行写操作只能进行读
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
//*it = 100; const使得当进行写操作时会报错会提示避免了进行修改操作
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1; //无参构造函数
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeuque(d1);
//区间的方式构造
deque<int>d2(d1.begin(),d1.end());
printDeuque(d2);
//n个值的方式构造
deque<int>d3(10,100);
printDeuque(d3);
//拷贝构造
deque<int>d4(d3);
printDeuque(d4);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8 9
- 100 100 100 100 100 100 100 100 100 100
- 100 100 100 100 100 100 100 100 100 100
- 请按任意键继续. . .
## 4.3 赋值操作
① 功能描述给deque容器进行赋值。
② 函数原型:
1. deque& operator=(const deque &deq); //重载等号操作符
2. assign(beg, end); //将[beg,end)区间中的数据拷贝赋值给本身。
3. assign(n,elem); //将n个elem拷贝赋值给本身。
③ deque赋值操作与vector相同。
```python
#include <iostream>
using namespace std;
#include<deque>
//deque容器 赋值操作
void printDeuque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeuque(d1);
//operator= 赋值
deque<int>d2;
d2 = d1;
printDeuque(d2);
//assign 赋值
deque<int>d3;
d3.assign(d1.begin(), d1.end());
printDeuque(d3);
deque<int>d4(10,100);
printDeuque(d4);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8 9
- 100 100 100 100 100 100 100 100 100 100
- 请按任意键继续. . .
## 4.4 大小操作
① 功能描述对deque容器的大小进行操作。
② 函数原型:
//判断容器是否为空
deque.empty();
//返回容器中的元素的个数
deque.size();
//重新指定容器的长度为num若容器变长则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num);
//重新指定容器的长度为num若容器变长则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num,elem);
```python
#include <iostream>
using namespace std;
#include<deque>
//deque容器 大小操作
void printDeuque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeuque(d1);
if (d1.empty())
{
cout << "d1为空" << endl;
}
else
{
cout << "d1不为空" << endl;
cout << "d1的大小为" << d1.size() << endl;
//deque容器没有容量概念
}
//重新指定大小
d1.resize(15, 1); //这里指定填充值为1如果没有第二个参数默认的填充值为0
printDeuque(d1);
d1.resize(5);
printDeuque(d1);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0 1 2 3 4 5 6 7 8 9
- d1不为空
- d1的大小为10
- 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1
- 0 1 2 3 4
- 请按任意键继续. . .
## 4.5 插入和删除
① 功能描述向deque容器中插入和删除数据。
② 函数原型:
两端插入操作:
1. push_back(elem); //在容器尾部添加一个数据
2. push_front(elem); //在容器头部插入一个数据
3. pop_back(); //删除容器最后一个数据
4. pop_front(); //删除容器第一个数据
指定位置操作:
1. insert(pos,elem); //在pos位置插入一个elem元素的拷贝返回新数据的位置。
2. insert(pos,n,elem); //在pos位置插入n个elem数据无返回值
3. insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值
4. clear(); //清空容器的所有数据
5. erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。
6. erase(pos); //删除pos位置的数据返回下一个数据的位置。
```python
#include <iostream>
using namespace std;
#include<deque>
//deque容器 插入和删除
void printDeuque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1;
//尾插
d1.push_back(10);
d1.push_back(20);
//头插
d1.push_front(100);
d1.push_front(200);
printDeuque(d1);
//尾删
d1.pop_back();
printDeuque(d1);
//头删
d1.pop_front();
printDeuque(d1);
}
void test02()
{
deque<int>d2;
d2.push_back(10);
d2.push_back(20);
d2.push_front(100);
d2.push_front(200);
printDeuque(d2);
d2.insert(d2.begin(), 1000);
printDeuque(d2);
d2.insert(d2.begin(), 2, 9999);
printDeuque(d2);
deque<int>d3;
d3.push_back(1);
d3.push_back(2);
d3.push_front(3);
d3.insert(d3.begin(), d2.begin(), d2.end()); //在d3.begin()的位置插入区间d2.begin()-d2.end()之间的数
printDeuque(d3);
}
void test03()
{
deque<int>d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
//删除
deque<int>::iterator it = d1.begin();
it++;
d1.erase(it); //d1.erase()为删除所有;d1.clear()也为清空容器所有数据
printDeuque(d1);
//按区间方式删除
d1.erase(d1.begin(), d1.end());
printDeuque(d1);
}
int main()
{
test01();
test02();
test03();
system("pause");
return 0;
}
```
运行结果:
- 200 100 10 20
- 200 100 10
- 100 10
- 200 100 10 20
- 1000 200 100 10 20
- 9999 9999 1000 200 100 10 20
- 9999 9999 1000 200 100 10 20 3 1 2
- 200 10 20
-
- 请按任意键继续. . .
## 4.6 数据存取
① 功能描述对deque中的数据的存取操作。
② 函数原型:
1. at(int idx); //返回索引idx所指的数据
2. operator[]; //返回索引idx所指的数据
3. front(); //返回容器中第一个数据元素
4. back(); //返回容器中最后一个数据元素
③ 除了用迭代器获取deque容器中元素[]和at也可以。
```python
#include <iostream>
using namespace std;
#include<deque>
//deque容器 数据存取
void printDeuque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1;
//尾插
d1.push_back(10);
d1.push_back(20);
d1.push_back(30);
//头插
d1.push_front(100);
d1.push_front(200);
d1.push_front(300);
//通过[]方式访问元素
//
for (int i = 0; i < d1.size(); i++)
{
cout << d1[i] << " ";
}
cout << endl;
//通过at方式访问元素
for (int i = 0; i < d1.size(); i++)
{
cout << d1.at(i) << " ";
}
cout << endl;
cout << "第一个元素为:" << d1.front() << endl;
cout << "最后一个元素为:" << d1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 300 200 100 10 20 30
- 300 200 100 10 20 30
- 第一个元素为300
- 最后一个元素为30
- 请按任意键继续. . .
## 4.7 排序
① 利用算法实现对deque容器进行排序。
② 算法:
1. sort(iterator beg, iterator end) //对beg和end区间内元素进行排序
③ sort算法非常实用使用时包含头文件algorithm即可。
```python
#include <iostream>
using namespace std;
#include<deque>
#include<algorithm> //标准算法头文件
//deque容器 排序操作
void printDeuque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) //表示只读迭代器
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d1;
//尾插
d1.push_back(10);
d1.push_back(20);
d1.push_back(30);
//头插
d1.push_front(100);
d1.push_front(200);
d1.push_front(300);
printDeuque(d1);
//排序 默认排序规则 从小到大 升序
//对于支持随机访问的迭代器的容器都可以利用sort算法直接对其进行排序
//vector容器也可以利用sort进行排序
sort(d1.begin(), d1.end());
cout << "排序后:" << endl;
printDeuque(d1);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 300 200 100 10 20 30
- 排序后:
- 10 20 30 100 200 300
- 请按任意键继续. . .
# 5. stack容器
## 5.1 简介
① stack是一种先进后出的容器它只有一个出口。
② 栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为。
③ 栈中进入数据称为:入栈 push
④ 栈中弹出数据称为:出栈 pop
![image.png](29_C++的STL_files/image.png)
## 5.2 常用接口
① 功能描述:栈容器常用的对外接口。
② 构造函数:
1. stack<T> stk; //stack采用模板类实现stack对象的默认构造形式
2. stack(const stack &stk); //拷贝构造函数
③ 赋值操作:
1. stack& operator=(const stack &stk); //重载等号操作符
④ 数据存取:
1. push(elem); //向栈顶添加元素
2. pop(); //从栈顶移除第一个元素
3. top(); //返回栈顶元素
⑤ 大小操作:
1. empty(); //判断堆栈是否为空
2. size(); //返回栈的大小
```python
#include<iostream>
using namespace std;
#include <stack>
//栈stack容器
void test01()
{
//特点符合先进后出数据结构
stack<int>s;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
//只要栈不为空查看栈顶并且执行出栈操作
while (!s.empty())
{
//查看栈顶元素
cout << "栈顶元素为:" << s.size() << endl;
//出栈
s.pop();
}
cout << "栈的大小:" << s.size() << endl;
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 栈顶元素为4
- 栈顶元素为3
- 栈顶元素为2
- 栈顶元素为1
- 栈的大小0
- 请按任意键继续. . .
# 6. queue容器
## 6.1 简介
① queue是一种先进先出的数据结构它有两个出口。
② 队列容器允许一段新增元素,从另一端移除元素。
③ 队列中只有对头和队尾才可以被外界使用,因此队列不运行有遍历行为。
④ 队列中进数据称为入队。
⑤ 队列中出数据称为出队。
## 6.2 常用接口
① 功能描述:栈容器常用的对外接口。
② 构造函数:
1. queue<T> que; //queue采用模板类实现queue对象的默认构造形式
2. queue(const queue &que); //拷贝构造函数
③ 赋值操作:
1. queue& operator=(const queue &que); //重载等号操作符
④ 数据存储:
1. push(elem); //往队尾添加元素
2. pop(); //从对头移除第一个元素
3. back(); //返回最后一个元素
4. front(); //返回第一个元素
⑤ 大小操作:
1. empty(); //判断堆栈是否为空
2. size(); //返回栈的大小
```python
#include<iostream>
using namespace std;
#include <queue>
#include<string>
//队列 Queue
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test01()
{
//创建队列
queue<Person>q;
//准备数据
Person p1("唐僧", 30);
Person p2("孙悟空", 1000);
Person p3("猪八戒", 900);
Person p4("沙僧", 800);
//入队
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 << endl;
//查看队尾
cout << "队尾元素 -- 姓名:" << q.back().m_Name << " 年龄:" << q.back().m_Age << endl;
//出对
q.pop(); //出队是出对头元素
}
cout << "队列大小为:" << q.size() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 队列大小为4
- 对头元素 -- 姓名:唐僧 年龄30
- 队尾元素 -- 姓名:沙僧 年龄800
- 对头元素 -- 姓名:孙悟空 年龄1000
- 队尾元素 -- 姓名:沙僧 年龄800
- 对头元素 -- 姓名:猪八戒 年龄900
- 队尾元素 -- 姓名:沙僧 年龄800
- 对头元素 -- 姓名:沙僧 年龄800
- 队尾元素 -- 姓名:沙僧 年龄800
- 队列大小为0
- 请按任意键继续. . .
# 7. list容器
## 7.1 简介
① 功能:将数据进行链式存储。
② 链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
③ 链表的组成:链表由一系列结点组成。
④ 结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
![image.png](29_C++的STL_files/image.png)
⑤ 添加元素,将原指向下一个元素的指针指向新元素即可,新元素指向下一个元素
![image.png](29_C++的STL_files/image.png)
⑥ STL中的链表是一个双向循环链表。
1. 双向:每一个指针既指向下一个结点的元素,也指向上一个结点的元素。
2. 循环:最后一个结点的指针会指向第一个结点的元素,第一个结点的指针会指向最后一个结点的元素。
![image.png](29_C++的STL_files/image.png)
⑦ 由于链表的存储方式并不是连续的内存空间因此链表list中的迭代器只支持前移和后移属于双向迭代器。
1. 它只能通过指针域一个一个前移/后移去找,而不能连续的内存空间,指针加一个数字,就可以找到数据。
⑧ list的优点
1. 采用动态存储分配,不会造成内存浪费和溢出。
2. 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量数据。
⑨ list的缺点
1. 链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大。
10.list有一个重要的性质插入操作和删除操作都不会造成原有list迭代器的失效这在vector中是不成立的vector当插入操作会创建一个更大的数据内容而vector容器的迭代器却指向原有内存所以原有的vector容器失效了。
11.STL中list和vector是两个最长被用的容器各有优缺点。
## 7.2 构造函数
① 功能描述创建list容器。
② 函数原型:
1. list<T> lst; //list采用模板类实现对象的默认构造形式
2. list(beg,end); //构造函数将[beg,end)区间中的元素拷贝给本身。
3. list(n,elem); //构造函数将n个elem拷贝给本身。
4. list(const list &lst); //拷贝构造函数。
③ list构造方式同其他几个STL容器一样。
```python
#include<iostream>
using namespace std;
#include <list>
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
//区间方式构造
list<int>L2(L1.begin(), L1.end());
printList(L2);
//拷贝构造
list<int>L3(L2);
printList(L3);
//n个elem
list<int>L4(10, 1000);
printList(L4);
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- 10 20 30 40
- 10 20 30 40
- 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000
- 请按任意键继续. . .
## 7.3 赋值和交换
① 功能描述给list容器进行赋值以及交换list容器。
② 函数原型:
1. assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身。
2. assign(n,elem); //将n个elem拷贝赋值给本身。
3. list& operator=(const list &list); //重载等号操作符。
4. swap(list); //将lst与本身的元素互换。
```python
#include<iostream>
using namespace std;
#include <list>
//list容器赋值和交换
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
list<int>L2;
L2 = L1; //operator= 赋值
printList(L2);
list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list<int>L4;
L4.assign(10, 100);
printList(L4);
}
//交换
void test02()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(10, 100);
cout << "交换前:" << endl;
printList(L1);
printList(L2);
L1.swap(L2);
cout << "交换后:" << endl;
printList(L1);
printList(L2);
}
int main() {
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- 10 20 30 40
- 10 20 30 40
- 100 100 100 100 100 100 100 100 100 100
- 交换前:
- 10 20 30 40
- 100 100 100 100 100 100 100 100 100 100
- 交换后:
- 100 100 100 100 100 100 100 100 100 100
- 10 20 30 40
- 请按任意键继续. . .
## 7.4 大小操作
① 功能描述对list容器的大小进行操作。
② 函数原型:
//返回容器中元素的个数。
1. size();
//判断容器是否为空。
2. empty();
//重新指定容器的长度为num若容器变长则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
3. resize(num);
//重新指定容器的长度为num若容器变成则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
4. resize(num,elem);
```python
#include<iostream>
using namespace std;
#include <list>
//list容器赋值和交换
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
//判断容器是否为空
if(L1.empty())
{
cout << "L1为空" << endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1的元素个数为" << L1.size() << endl;
}
//重新指定大小
L1.resize(10,10000);
printList(L1);
L1.resize(2);
printList(L1);
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- L1不为空
- L1的元素个数为4
- 10 20 30 40 10000 10000 10000 10000 10000 10000
- 10 20
- 请按任意键继续. . .
## 7.5 插入和删除
① 功能描述对list容器进行数据的插入和删除。
② 函数原型:
1. push_back(elem); //在容器尾部加入一个元素。
2. pop_back(); //删除容器中最后一个元素。
3. push_front(elem); //在容器开头插入一个元素。
4. pop_front(); //从哪个容器开头移除第一个元素
5. insert(pos,elem); //在pos位置插elem元素的拷贝返回新数据的位置。
6. insert(pos,n,elem); //在pos位置插入n个elem数据无返回值。
7. insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值。
8. clear(); //移除容器的所有数据。
9. erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。
10. erase(pos); //删除pos位置的数据返回下一个数据的位置。
11. remove(elem); //删除容器中所有与elem值匹配的元素。
```python
#include<iostream>
using namespace std;
#include <list>
//list容器赋值和交换
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_front(100);
L1.push_front(200);
L1.push_front(300);
//遍历容器
printList(L1);
//尾删
L1.pop_back();
printList(L1);
//头删
L1.pop_front();
printList(L1);
//insert插入
list<int>::iterator it = L1.begin();
L1.insert(++it, 1000);
printList(L1);
//删除
it = L1.begin();
L1.erase(it);
printList(L1);
//移除
L1.push_back(10000);
L1.push_back(10000);
L1.push_back(10000);
L1.push_back(10000);
printList(L1);
L1.remove(10000);
printList(L1);
//清空
L1.clear();
printList(L1);
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 300 200 100 10 20 30
- 300 200 100 10 20
- 200 100 10 20
- 200 1000 100 10 20
- 1000 100 10 20
- 1000 100 10 20 10000 10000 10000 10000
- 1000 100 10 20
-
- 请按任意键继续. . .
## 7.6 数据存取
① 功能描述对list容器中数据进行存取。
② 函数原型:
1. front(); //返回第一个元素。
2. back(); //返回最后一个元素。
③ list容器不是连续的内存空间所以不能通过[]、at等方式随机访问。
```python
#include<iostream>
using namespace std;
#include <list>
//list容器 数据存取
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
list<int>L1; //默认构造
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//L1[0] 不可以用[]访问list容器中的元素
//L1.at(0) 不可以用at方式访问list容器中的元素
//原因是list本质链表不是用连续线性空间存储数据迭代器也是不支持随机访问的
cout << "第一个元素为:" << L1.front() << endl;
cout << "第一个元素为:" << L1.back() << endl;
//验证迭代器是不支持随机访问的
list<int>::iterator it = L1.begin();
it++; //因为list是双向的所以支持递增递减++--的操作但是不支持it = it+1;it = it+2;....即不支持这样的随机访问
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 第一个元素为10
- 第一个元素为40
- 请按任意键继续. . .
## 7.7 反转和排序
① 功能描述:将容器中的元素反转,以及将容器中的数据进行排序。
② 函数原型:
1. reverse(); //反转链表
2. sort(); //链表排序
```python
#include<iostream>
using namespace std;
#include <list>
#include<algorithm>
//list容器 反转和排序
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool myCopare(int v1, int v2)
{
//降序 就让第一个数 大于第二个数为真
return v1 > v2;
}
void test01()
{
//反转
list<int>L1;
//添加数据
L1.push_back(20);
L1.push_back(10);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
cout << "反转前:" << endl;
printList(L1);
//反转
L1.reverse();
cout << "反转后:" << endl;
printList(L1);
//排序
cout << "排序前:" << endl;
printList(L1);
//所有不支持随机访问迭代器的容器不可以用标准算法
//不支持随机访问迭代器的容器内部会提供对应的一些算法
//sort(L1.begin(),L1.end()); //报错这是标准算法全局函数的sort()
L1.sort(); //默认排序规则 从小到大 升序
cout << "排序后:" << endl;
printList(L1);
L1.sort(myCopare); //降序排列 这是成员函数的sort()
cout << "重载排序算法,降序排序后:" << endl;
printList(L1);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 反转前:
- 20 10 50 40 30
- 反转后:
- 30 40 50 10 20
- 排序前:
- 30 40 50 10 20
- 排序后:
- 10 20 30 40 50
- 重载排序算法,降序排序后:
- 50 40 30 20 10
- 请按任意键继续. . .
# 8. set容器
## 8.1 简介
① set容器中所有元素在插入时自动被排序。
② set容器和multiset容器属于关联式容器底层结构用二叉树实现。
③ set容器与multiset容器区别
1. set容器不允许容器中有重复的元素。
2. multiset容器允许容器中有重复的元素。
## 8.2 构造和赋值
① 功能描述创建set容器以及赋值。
② 构造函数:
1. set<T> st; //默认构造函数
2. set(const set &st); //拷贝构造函数
③ 赋值函数:
1. set& operator=(const set &st); //重载等号操作符
④ set容器插入数据时用insert。
⑤ set容器插入的数据会自动排序。
```python
#include<iostream>
using namespace std;
#include <set>
//set容器 构造和赋值
void printset(const set<int>&L)
{
for (set<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool myCopare(int v1, int v2)
{
//降序 就让第一个数 大于第二个数为真
return v1 > v2;
}
void test01()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(30);
s1.insert(20);
s1.insert(30);
//遍历容器
//set容器特点所有元素插入时候自动被排序
//set容器不允许插入重复值
printset(s1);
//拷贝构造
set<int>s2(s1);
printset(s2);
//赋值
set<int>s3;
s3 = s2;
printset(s3);
}
int main() {
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- 10 20 30 40
- 10 20 30 40
- 请按任意键继续. . .
## 8.3 大小和交换
① 功能描述统计set容器大小以及交换set容器。
② 函数原型:
1. size(); //返回容器中元素的数目。
2. empty(); //判断容器是否为空。
3. swap(st); //交换两个集合容器
```python
#include<iostream>
using namespace std;
#include <set>
//set容器 大小和交换
void printset(const set<int>&L)
{
for (set<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//大小
void test01()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(30);
s1.insert(20);
s1.insert(30);
printset(s1);
//判断是否为空
if (s1.empty())
{
cout << "s1为空" << endl;
}
else
{
cout << "s1不为空" << endl;
cout << "s1的大小为" << s1.size() << endl;
}
}
//交换
void test02()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(30);
s1.insert(20);
s1.insert(30);
set<int>s2;
//插入数据 只有insert方式
s2.insert(100);
s2.insert(400);
s2.insert(300);
s2.insert(200);
s2.insert(300);
cout << "交换前:" << endl;
printset(s1);
printset(s2);
cout << "交换后:" << endl;
s1.swap(s2);
printset(s1);
printset(s2);
}
int main() {
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- s1不为空
- s1的大小为4
- 交换前:
- 10 20 30 40
- 100 200 300 400
- 交换后:
- 100 200 300 400
- 10 20 30 40
- 请按任意键继续. . .
## 8.4 插入和删除
① 功能描述set容器进行插入数据和删除数据。
② 函数原型:
1. insert(elem); //在容器中插入元素。
2. clear(); //清除所有元素。
3. erase(pos); //删除pos迭代器所指的元素返回下一个元素的迭代器。
4. erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器。
5. erase(elem); //删除容器中值为elem的元素。
```python
#include<iostream>
using namespace std;
#include <set>
//set容器 插入和删除
void printset(const set<int>&L)
{
for (set<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(20);
s1.insert(40);
s1.insert(30);
s1.insert(10);
s1.insert(30);
printset(s1);
//删除
s1.erase(s1.begin()); //删掉的是排序后的第一个元素10
printset(s1);
//删除函数的重载版本
s1.erase(30); //删除30这个元素
printset(s1);
//清空方式一
s1.erase(s1.begin(), s1.end());
printset(s1);
//清空方式二
s1.clear();
printset(s1);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- 20 30 40
- 20 40
-
-
- 请按任意键继续. . .
## 8.5 查找和统计
① 功能描述对set容器进行查找书籍以及统计数据。
② 函数原型:
1. find(key); //查找key是否存在若存在返回该键的元素的迭代器若不存在返回set.end();
2. cout(key); //统计key的元素个数。
```python
#include<iostream>
using namespace std;
#include <set>
//set容器 查找和统计
void printset(const set<int>&L)
{
for (set<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(20);
s1.insert(40);
s1.insert(30);
s1.insert(10);
s1.insert(30);
printset(s1);
//查找返回的是一个迭代器
set<int>::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout << "找到元素:" << *pos << endl;
}
else
{
cout << "未找到元素" << endl;
}
}
//统计
void test02()
{
set<int>s1;
//插入数据 只有insert方式
s1.insert(20);
s1.insert(40);
s1.insert(30);
s1.insert(10);
s1.insert(30);
int num = s1.count(30);
//对于set而言 统计结果要么是0 要么是1
cout << "num = " << num << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40
- 找到元素30
- num = 1
- 请按任意键继续. . .
## 8.6 set和multiset区别
① set和multiset区别
1. set不可以插入重复数据而multiset可以。
2. set插入数据的同时会返回插入结果表示插入是否成功。
3. mutiset不会检测数据因此可以插入重复数据。
② 如果不允许插入重复数据可以利用set
③ 如果需要插入重复数据利用mutiset
```python
#include<iostream>
using namespace std;
#include <set>
//set容器 mutiset容器 的区别
void printset(const set<int>&L)
{
for (set<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;
pair<set<int>::iterator, bool> ret = s1.insert(10); //s.insert()返回的是pair类型第一个数为迭代器第二个数为布尔类型
if (ret.second)
{
cout << "第一次插入成功" << endl;
}
else
{
cout << "第一次插入失败" << endl;
}
ret = s1.insert(10); //set不允许插入重复的值当插入重复的值返回的第二个参数为False然后不会插入进去
if (ret.second)
{
cout << "第二次插入成功" << endl;
}
else
{
cout << "第二次插入失败" << endl;
}
multiset<int>ms;
//运行插入重复值
ms.insert(10);
ms.insert(10);
ms.insert(10);
for (multiset<int>::const_iterator it = ms.begin(); it != ms.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 第一次插入成功
- 第二次插入失败
- 10 10 10
- 请按任意键继续. . .
## 8.7 内置类型指定排序规则
① set容器默认排序规则从小到大利用仿函数可以改变排序规则。
```python
#include<iostream>
using namespace std;
#include <set>
//set容器排序
class MyCompare
{
public:
bool operator()(int v1, int v2)const //第一个()表示重载符号第二个()为参数列表
{
return v1 > v2;
}
};
void test01()
{
set<int>s1; //set容器默认从小到大排序
s1.insert(10);
s1.insert(40);
s1.insert(50);
s1.insert(20);
s1.insert(30);
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//指定排序规则为从大到小
set<int, MyCompare>s2; //此时指定set容器的排序规则为MyCompareMyCompare()
s2.insert(10);
s2.insert(40);
s2.insert(50);
s2.insert(20);
s2.insert(30);
for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 10 20 30 40 50
- 50 40 30 20 10
- 请按任意键继续. . .
## 8.8 自定义数据类型指定排序规则
```python
#include<iostream>
using namespace std;
#include <set>
//set容器排序
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
class comparePerson //仿函数本质是一个类
{
public:
bool operator()(const Person& p1, const Person& p2)const
{
//安装年龄 降序
return p1.m_Age > p2.m_Age;
}
};
void test01()
{
//自定义数据类型 都会指定排序规则
set<Person, comparePerson>s1;
//创建Person对象
Person p1("刘备", 24);
Person p2("关羽", 28);
Person p3("张飞", 25);
Person p4("赵云", 21);
s1.insert(p1);
s1.insert(p2);
s1.insert(p3);
s1.insert(p4);
for (set<Person, comparePerson>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << "姓名:" << it->m_Name << "年龄:" << it->m_Age << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 姓名关羽年龄28
- 姓名张飞年龄25
- 姓名刘备年龄24
- 姓名赵云年龄21
- 请按任意键继续. . .
# 9. map容器
## 9.1 简介
① map容器中的所有元素都是pair。
② pair中第一个元素为key(键值)起到索引作用第二个元素为value(实值)。
③ 所有元素都会根据元素的键值自动排序。
④ map容器和multimap容器属于关联式容器底层结构是用二叉树实现。
⑤ map容器可以根据key值快速找到value值。
⑥ map和multimap区别
1. map不允许容器中有重复key值元素。
2. mutimap运行容器中有重复的key值元素。
## 9.2 pair对组的创建
① 功能描述:成对出现的数据,利用对组可以返回两个数据。
② 两种创建方式:
1. pair<type,type> p (value1, value2);
2. pair<type,type> p = make_pair(value1,value2);
③ 两种方式都可以创建对组,记住一种即可。
```python
#include<iostream>
using namespace std;
#include <set>
//pair对组的创建
void test01()
{
//第一种方式
pair<string, int>p("Tom", 20);
cout << "姓名:" << p.first << "年龄:" << p.second << endl;
//第二种方式
pair<string, int>p2 = make_pair("Jerry", 30);
cout << "姓名:" << p2.first << "年龄:" << p2.second << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 姓名Tom年龄20
- 姓名Jerry年龄30
- 请按任意键继续. . .
## 9.3 map容器构造和赋值
① 功能描述对map容器进行构造和赋值操作。
② 构造函数:
1. map<T1,T2> mp; //map默认构造函数
2. map(const map &mp); //拷贝构造函数
③ 赋值操作:
1. map& operator=(const map &mp); //重载等号操作符
④ map容器中所有元素都是成对出现插入元素时候需要使用对组。
```python
#include<iostream>
using namespace std;
#include <map>
//map容器 构造和赋值
void printMap(map<int, int>& m)
{
for (map<int,int>::iterator it = m.begin();it!=m.end();it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
//创建map容器
map<int, int>m;
m.insert(pair<int, int>(1, 10)); //1为key10为value
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(4, 40));
printMap(m);
//拷贝构造
map<int, int>m2(m);
printMap(m);
//赋值
map<int, int>m3;
m3 = m2;
printMap(m3);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
- key = 4 value = 40
-
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
- key = 4 value = 40
-
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
- key = 4 value = 40
-
- 请按任意键继续. . .
## 9.4 map容器大小和交换
① 功能描述统计map容器大小以及交换map容器。
② 函数原型:
1. size(); //返回容器中元素的数目。
2. empty(); //判断容器是否为空。
3. swap(st); //交换两个集合容器。
```python
#include<iostream>
using namespace std;
#include <map>
void printMap(map<int, int>& m)
{
for (map<int,int>::iterator it = m.begin();it!=m.end();it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
//大小
void test01()
{
//创建map容器
map<int, int>m;
m.insert(pair<int, int>(1, 10)); //1为key10为value
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 20));
printMap(m);
if (m.empty())
{
cout << "m为空" << endl;
}
else
{
cout << "m不为空" << endl;
cout << "m的大小" << m.size() << endl;
}
}
//交换
void test02()
{
map<int, int>m1;
m1.insert(pair<int, int>(1, 10)); //1为key10为value
m1.insert(pair<int, int>(3, 30));
m1.insert(pair<int, int>(2, 20));
map<int, int>m2;
m2.insert(pair<int, int>(4, 100));
m2.insert(pair<int, int>(5, 300));
m2.insert(pair<int, int>(6, 200));
cout << "交换前:" << endl;
printMap(m1);
printMap(m2);
m1.swap(m2);
cout << "交换后:" << endl;
printMap(m1);
printMap(m2);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
```
运行结果:
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
-
- m不为空
- m的大小3
- 交换前:
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
-
- key = 4 value = 100
- key = 5 value = 300
- key = 6 value = 200
-
- 交换后:
- key = 4 value = 100
- key = 5 value = 300
- key = 6 value = 200
-
- key = 1 value = 10
- key = 2 value = 20
- key = 3 value = 30
-
- 请按任意键继续. . .
## 9.5 map容器插入和删除
① 功能描述map容器进行插入数据和删除数据。
② 函数原型:
1. insert(elem); //在容器中插入元素。
2. clear(); //清除所有元素。
3. erase(pos); //删除pos迭代器所指的元素返回下一个元素的迭代器。
4. erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器。
5. erase(key); //删除容器中值为key的元素。
③ map插入方式很多记住其一即可。
```python
#include<iostream>
using namespace std;
#include <map>
void printMap(map<int, int>& m)
{
for (map<int,int>::iterator it = m.begin();it!=m.end();it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
//创建map容器
map<int, int>m;
//第一种
m.insert(pair<int, int>(1, 10));
//第二种
m.insert(make_pair(2, 10));
//第三种
m.insert(map<int, int>::value_type(3, 30)); //map容器下为"值"(3,30)
//第四种
m[4] = 40;
cout << m[5] << endl; //由于没有m[5]没有数它会自动创建出一个value为0的数
cout << m[4] << endl; //不建议用[]插入但是可以利用key访问到value
printMap(m);
//删除
m.erase(m.begin());
printMap(m);
m.erase(3); //安装key删除
printMap(m);
//清空方式一
m.erase(m.begin(),m.end());
//清空方式二
m.clear();
printMap(m);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 0
- 40
- key = 1 value = 10
- key = 2 value = 10
- key = 3 value = 30
- key = 4 value = 40
- key = 5 value = 0
-
- key = 2 value = 10
- key = 3 value = 30
- key = 4 value = 40
- key = 5 value = 0
-
- key = 2 value = 10
- key = 4 value = 40
- key = 5 value = 0
-
-
- 请按任意键继续. . .
## 9.6 map容器查找和统计
① 对map容器进行查找数据以及统计数据。
② 函数原型:
1. find(key); //查找key是否存在若存在返回该键的元素的迭代器若不存在返回set.end();
2. cout(key); //统计key的元素个数。
```python
#include<iostream>
using namespace std;
#include <map>
void test01()
{
//创建map容器
map<int, int>m;
m.insert(pair<int,int>(1, 10));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int,int>(2, 20));
m.insert(pair<int, int>(3, 30));
map<int,int>::iterator pos = m.find(3);
if (pos != m.end())
{
cout << "查到了元素 key = " << (*pos).first << " value = " << pos->second << endl;
}
else
{
cout << "未找到元素" << endl;
}
//统计
//map不允许插入重复key元素count统计而言 结果要么是0 要么是1
//mutimap 的count统计可以大于1
int num = m.count(3);
cout << "num = " << num << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 查到了元素 key = 3 value = 30
- num = 1
- 请按任意键继续. . .
## 9.7 map容器排序
① map容器默认排序规则为按照key值进行从小到大排序利用仿函数可以改变排序规则。
② 利用仿函数可以指定map容器的排序规则。
③ 对于自定义数据类型map必须要指定排序规则同set容器。
```python
#include<iostream>
using namespace std;
#include <map>
class MyCompare
{
public:
bool operator()(int v1, int v2)const
{
//降序
return v1 > v2;
}
};
void printMap(map<int, int, MyCompare>& m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
//创建map容器
//不是插了之后再排序而是在创建的时候就排序
map<int, int, MyCompare>m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
printMap(m);
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- key = 5 value = 50
- key = 4 value = 40
- key = 3 value = 30
- key = 2 value = 20
- key = 1 value = 10
-
- 请按任意键继续. . .
# 10. 评委打分
① 案例描述选手ABCDE10个评委分别对每一名选手打分去除最高分去除评委中最低分取平均分。
② 实现步骤:
1. 创建五名选手放到vector容器中。
2. 遍历vector容器取出来每一个选手执行for循环可以把10个评委打分存到deque容器中。
3. sort算法对deque容器中分数进行排序去除最高分和最低分。
4. deque容器遍历一遍累加总分。
5. 获取平均分。
```python
#include <iostream>
using namespace std;
#include<vector>
#include<deque>
#include<string>
#include<algorithm> //标准算法头文件
#include<ctime>
//选手类
class Person
{
public:
Person(string name, int score)
{
this->m_Name = name;
this->m_Score = score;
}
string m_Name; //姓名
int m_Score; //平均分
};
void createPerson(vector<Person>& v)
{
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++)
{
string name = "选手";
name += nameSeed[i];
int score = 0;
Person p(name, score);
//将创建的person对象放入到容器中
v.push_back(p);
}
}
//2给5名选手打分
void setScore(vector<Person>& v)
{
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
//将评委的分数 放入到deque容器中
deque<int>d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 41 + 60; // 60~100
d.push_back(score);
}
cout << "选手:" << it->m_Name << "打分:" << endl;
for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
{
cout << *dit << " ";
}
cout << endl;
//排序
sort(d.begin(), d.end());
//去除最高分和最低分
d.pop_back();
d.pop_front();
//取平均分
int sum = 0;
for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
{
sum += *dit; //累加每个评委的分数
}
int avg = sum / d.size();
//将平均分 赋值给选手身上
it->m_Score = avg;
}
}
void showScore(vector<Person>&v)
{
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名:" << it->m_Name << "平均分" << it->m_Score << endl;
}
}
int main()
{
srand((unsigned int)time(NULL));
//1创建5名选手
vector<Person>v; //存放选手容器
createPerson(v);
//测试
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名:" << (*it).m_Name << "分数:" << (*it).m_Score << endl;
}
//2给5名选手打分
setScore(v);
//3显示最后得分
showScore(v);
system("pause");
return 0;
}
```
运行结果:
- 姓名选手A分数0
- 姓名选手B分数0
- 姓名选手C分数0
- 姓名选手D分数0
- 姓名选手E分数0
- 选手选手A打分
- 87 90 93 71 96 67 60 83 64 73
- 选手选手B打分
- 88 72 66 97 62 90 93 95 100 63
- 选手选手C打分
- 63 85 71 63 92 64 89 90 89 98
- 选手选手D打分
- 98 61 62 76 62 74 90 65 85 68
- 选手选手E打分
- 87 67 96 60 75 63 92 76 98 75
- 姓名选手A平均分78
- 姓名选手B平均分83
- 姓名选手C平均分80
- 姓名选手D平均分72
- 姓名选手E平均分78
- 请按任意键继续. . .
# 11. 年龄排序
① 案例描述将Person自定义数据类型进行排序Person中属性有姓名、年龄、身高。
② 排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序。
```python
#include<iostream>
using namespace std;
#include <list>
#include<string>
#include<algorithm>
//list容器 排序案例 对于自定义数据类型 做排序
//按照年龄进行升序 如果年龄相同 按照身高进行降序
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 test01()
{
list<Person>L; //创建容器
//准备数据
Person p1("刘备", 35, 175);
Person p2("刘备", 45, 180);
Person p3("刘备", 50, 170);
Person p4("刘备", 25, 190);
Person p5("刘备", 35, 160);
Person p6("刘备", 35, 200);
//插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Height << endl;
}
//排序
cout << "---------------" << endl;
cout << "排序后:" << endl;
//L.sort(); 报错自定义数据类型编译器不知道怎么排序
L.sort(comparePerson);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Height << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
```
运行结果:
- 姓名:刘备 年龄35 身高175
- 姓名:刘备 年龄45 身高180
- 姓名:刘备 年龄50 身高170
- 姓名:刘备 年龄25 身高190
- 姓名:刘备 年龄35 身高160
- 姓名:刘备 年龄35 身高200
- $ --------------- $
- 排序后:
- 姓名:刘备 年龄25 身高190
- 姓名:刘备 年龄35 身高200
- 姓名:刘备 年龄35 身高175
- 姓名:刘备 年龄35 身高160
- 姓名:刘备 年龄45 身高180
- 姓名:刘备 年龄50 身高170
- 请按任意键继续. . .
# 12. 员工分组
案例描述:
1. 公司今天招募了10个员工ABCDEFGHIJ10名员工进入公司之后需要指派员工在那个部门工作。
2. 员工信息由:姓名 工资。部门为:策划、美术、研发。
3. 随机给10名员工分配部门和工资。
4. 通过multimap进行信息的插入。key(部门编号)value员工
5. 分部门显示员工信息。
实现步骤:
1. 创建10名员工放到vector中
2. 遍历vector容器取出每个员工进行随机分组。
3. 分组后将员工部门编号为key具体员工作为value放入到multimao容器中。
4. 分部门显示员工信息。
```python
#include<iostream>
using namespace std;
#include <vector>
#include <map>
#include<string>
#include<ctime>
/*
实现步骤
1. 创建10名员工放到vector中
2. 遍历vector容器取出每个员工进行随机分组
3. 分组后将员工部门编号为key具体员工作为value放入到multimao容器中
4. 分部门显示员工信息
*/
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
class Worker
{
public:
string m_Name;
int m_Salary;
};
void createWorker(vector<Worker>&v)
{
string nameSeed = "ABCDEFGHIJ";
for (int i = 0; i < 10; i++)
{
Worker worker;
worker.m_Name = "员工";
worker.m_Name += nameSeed[i];
worker.m_Salary = rand() % 10000 + 10000; //10000~19999
//将员工放入到容器中
v.push_back(worker);
}
}
void setGroup(vector<Worker>&v,multimap<int,Worker>&m)
{
for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
{
//产生随机部门编号
int depeId = rand() % 3;//0 1 2
//将员工插入到分组中
//key代表部门编号value代表具体员工
m.insert(make_pair(depeId, *it));
}
}
void showWorkerByGourp(multimap<int,Worker>&m)
{
//0 A B C 1 D E 2 F G
cout << "策划部门:" << endl;
multimap<int, Worker>::iterator pos = m.find(CEHUA);
int count = m.count(CEHUA); //统计具体人数
int index = 0;
for (; pos != m.end() && index < count; pos++,index++)
{
cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
}
cout << "--------" << endl;
cout << "美术部门:" << endl;
pos = m.find(MEISHU);
count = m.count(MEISHU); //统计具体人数
index = 0;
for (; pos != m.end() && index < count; pos++, index++)
{
cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
}
cout << "--------" << endl;
cout << "研发部门:" << endl;
pos = m.find(YANFA);
count = m.count(YANFA); //统计具体人数
index = 0;
for (; pos != m.end() && index < count; pos++, index++)
{
cout << "姓名:" << pos->second.m_Name << "工资:" << pos->second.m_Salary << endl;
}
}
int main()
{
srand((unsigned int)time(NULL));
//1创建员工
vector<Worker>vWorker;
createWorker(vWorker);
//2员工分组
//012号代表不同部门
multimap<int, Worker>mWorker;
setGroup(vWorker, mWorker);
//3分组显示员工
showWorkerByGourp(mWorker);
//测试
cout << "--------" << endl;
cout << "测试:" << endl;
for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++)
{
cout << "姓名:" << it->m_Name << " 工资:" << it->m_Salary << endl;
}
system("pause");
return 0;
}
```
运行结果:
- 策划部门:
- 姓名员工B工资11578
- - 姓名员工D工资11655
- 姓名员工G工资16818
- 姓名员工J工资12160
- $--------$
- 美术部门:
- 姓名员工F工资12782
- 姓名员工H工资15815
- $--------$
- 研发部门:
- 姓名员工A工资16686
- 姓名员工C工资10638
- 姓名员工E工资11730
- 姓名员工I工资17047
- $--------$
- 测试:
- 姓名员工A 工资16686
- 姓名员工B 工资11578
- 姓名员工C 工资10638
- 姓名员工D 工资11655
- 姓名员工E 工资11730
- 姓名员工F 工资12782
- 姓名员工G 工资16818
- 姓名员工H 工资15815
- 姓名员工I 工资17047
- 姓名员工J 工资12160
- 请按任意键继续. . .