1、STL初识
1.1 STL诞生
- C++的面向对象和泛型编程思想,目的就是复用性的提升
- 为了建立数据结构和算法的一套标准,诞生了STL
1.2 STL基本概念
- STL(standard Template Library),标准模板库
- STL从广义上分为:容器(container)算法(algorithm)和迭代器(iterator)
- 容器和算法之间通过迭代器进行无缝连接
- STL几乎所有的代码都采用了模版类或者模版函数
1.3 STL六大组件
- 容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
- 容器:各种数据结构,vector、list、deque、set、map等
- 算法:sort、find、copy、for_each
- 迭代器:扮演了容器与算法之间的胶合剂
- 仿函数:行为类似函数,可作为算法的某种策略
- 适配器:用来修饰容器或者仿函数或者迭代器接口的东西
- 空间配置器:负责空间的配置和管理
1.4 STL中容器、算法、迭代器
- STL容器就是将运用最广泛的一些数据结构实现出来
- 这些容器分为序列式容器和关联式容器两种:
- 序列式容器:强调值的排序,每个元素均有固定的位置
- 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
- 算法:有限的步骤,解决逻辑或数学上的问题
- 算法分为质变算法和非质变算法
- 质变算法:是指运算过程中会更改区间内的元素内容,例如拷贝、替换、删除等
- 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等
- 迭代器:容器和算法之间的粘合剂
- 迭代器提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无须暴露该容器的内部表示方式,每个容器有自己专属的迭代器
- 类似于指针
- 迭代器的分类
| 种类 | 功能 | 支持运算 |
| ——- | —————————- | —————————— |
| 输入迭代器 | 对数据的只读访问 | ++、==、!= |
| 输出迭代器 | 对数据的只写访问 | ++ |
| 前向迭代器 | 读写操作,只能向前推荐迭代器 | ++、==、!= |
| 双向迭代器 | 读写操作,能向前和向后操作 | ++、– |
| 随机访问迭代器 | 读写操作,可以以跳跃的方式访
问任意数据,功能最强 | ++、–、[n]、
-n、<、<=、>、
>= |
常用的容器中迭代器种类为双向迭代器和随机访问迭代器
1.5 初识容器
1.5.1 vector容器存放内置数据类型
vector
- 算法
for_each
- 迭代器
vector<int>::iterator
1.5.2 vector容器中存放自定义数据类型
- 迭代器的迭代对象相当于一个指针
1.5.3 vector容器嵌套容器
- 容器中嵌套容器,将所有元素输出
2、常用容器
2.1 String容器
- string 是 C++ 风格的字符串,本质上string是另一个类
string
和char*
的区别:char*
是一个指针- string是一个类,类内部封装了char*,管理这个字符串,是一个
char*
型的容器
- 特点:
- string类内部封装了很多成员方法,例如查找find,拷贝copy,删除delete,插入insert
string
管理char*
分配的内存,不用担心复制越界和取值越界等,由类的内部进行管理2.1.1 string构造函数
string();
string(const char* s);
string(const string& s);
string(int n, char c);
2.1.2 string的赋值操作
string &operator=(const char* s);
string &operator=(const string& s);
string &operator=(const char c);
string &assign(const char*s);
string &assign(const char*s, int n);
字符串的前n个赋值string &assign(const string &s);
string &assign(int n, char c);
2.4 评委打分案例
2.4.1 案例描述
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
2.4.2 实现步骤
- 创建五名选手,放到vector中
- 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
- sort算法对deque容器中分数排序,去除最高和最低分
- deque容器遍历一遍,累加总分
- 获取平均分
2.10 员工分组
2.10.1 案例描述
- 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作
- 员工信息有: 姓名 工资 部门(策划、美术、研发)
- 随机给10名员工分配部门和工资
- 通过multimap进行信息的插入 key(部门编号) value(员工)
- 分部门显示员工信息
2.10.2 实现步骤
- 创建10名员工,放到vector中
- 遍历vector容器,取出每个员工,进行随机分组
- 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
- 分部门显示员工信息
2.10.3 实现代码
```C++ #include
using namespace std; #include #include #include <map> #include
#define CEHUA 0 #define MEISHU 1 #define YANFA 2
class Worker { public: string m_Name; int m_Salary; };
void createWorker(vector
worker.m_Salary = rand() % 10000 + 10000; // 10000 ~ 19999
//将员工放入到容器中
v.push_back(worker);
} }
//员工分组
void setGroup(vector
//将员工插入到分组中
//key部门编号,value具体员工
m.insert(make_pair(deptId, *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、员工分组
multimap<int, Worker>mWorker;
setGroup(vWorker, mWorker);
//3、分组显示员工
showWorkerByGourp(mWorker);
////测试
//for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++)
//{
// cout << "姓名: " << it->m_Name << " 工资: " << it->m_Salary << endl;
//}
system("pause");
return 0; } ```
总结:
- 当数据以键值对形式存在,可以考虑用map 或 multimap