STL基础

Posted by LemonWhale on May 4, 2024

1、STL初识

1.1 STL诞生

  • C++的面向对象和泛型编程思想,目的就是复用性的提升
  • 为了建立数据结构和算法的一套标准,诞生了STL

    1.2 STL基本概念

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

    1.3 STL六大组件

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

      1.4 STL中容器、算法、迭代器

  • STL容器就是将运用最广泛的一些数据结构实现出来
  • 这些容器分为序列式容器关联式容器两种:
    1. 序列式容器:强调值的排序,每个元素均有固定的位置
    2. 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
  • 算法:有限的步骤,解决逻辑或数学上的问题
  • 算法分为质变算法和非质变算法
    1. 质变算法:是指运算过程中会更改区间内的元素内容,例如拷贝、替换、删除等
    2. 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等
  • 迭代器:容器和算法之间的粘合剂
  • 迭代器提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无须暴露该容器的内部表示方式,每个容器有自己专属的迭代器
  • 类似于指针
  • 迭代器的分类

| 种类 | 功能 | 支持运算 | | ——- | —————————- | —————————— | | 输入迭代器 | 对数据的只读访问 | ++、==、!= | | 输出迭代器 | 对数据的只写访问 | ++ | | 前向迭代器 | 读写操作,只能向前推荐迭代器 | ++、==、!= | | 双向迭代器 | 读写操作,能向前和向后操作 | ++、– | | 随机访问迭代器 | 读写操作,可以以跳跃的方式访
问任意数据,功能最强 | ++、–、[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是另一个类
  • stringchar*的区别:
    1. char* 是一个指针
    2. string是一个类,类内部封装了char*,管理这个字符串,是一个 char* 型的容器
  • 特点:
    1. string类内部封装了很多成员方法,例如查找find,拷贝copy,删除delete,插入insert
    2. 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 实现步骤
  1. 创建五名选手,放到vector中
  2. 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
  3. sort算法对deque容器中分数排序,去除最高和最低分
  4. deque容器遍历一遍,累加总分
  5. 获取平均分

    2.10 员工分组

    2.10.1 案例描述
  • 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作
  • 员工信息有: 姓名 工资 部门(策划、美术、研发)
  • 随机给10名员工分配部门和工资
  • 通过multimap进行信息的插入 key(部门编号) value(员工)
  • 分部门显示员工信息
    2.10.2 实现步骤
    1. 创建10名员工,放到vector中
    2. 遍历vector容器,取出每个员工,进行随机分组
    3. 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
    4. 分部门显示员工信息
      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&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&v,multimap<int,Worker>&m) { for (vector::iterator it = v.begin(); it != v.end(); it++) { //产生随机部门编号 int deptId = rand() % 3; // 0 1 2

	//将员工插入到分组中
	//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