1.11 C++ STL
一、STL 容器
- 序列容器:vector、list、forward_list、deque、array、string
- 关联式容器(自动排序、基于红黑树):set、map、multiset、multimap
- 无序关联式容器(基于哈希表):unordered_set、unordered_map、unordered_multiset、unordered_multimap
- 适配器容器(是对其他容器的封装):stack、queue、priority_queue
二、STL 算法
std::vector<int> v {1, 2, 3, 4};
auto it = std::find(v.begin(), v.end(), 3); // 返回迭代器
if (it != v.end()) std::cout << "Found at: " << it - v.begin();
std::sort(v.begin(), v.end()); // 默认升序
std::sort(v.begin(), v.end(), std::greater<int>()); // 降序
// 1、优先使用 lambda
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// 2、使用 仿函数
struct Compare {
bool operator()(int a, int b) const {
return a < b; // 升序排序
}
};
std::sort(v.begin(), v.end(), Compare());
// 3、自定义比较函数
bool compare(int a, int b) {
return a > b; // 降序排序
}
std::sort(v.begin(), v.end(), compare);
三、所有容器共有的核心方法
方法 | 作用 | 示例(以 |
| 判断容器是否为空 |
|
| 返回元素数量 |
|
| 清空容器 |
|
| 交换两个容器的内容 |
|
| 返回迭代器(含const版本) |
|
四、vector
vector<int> a;
vector<int> a(n);
vector<int> a(n,1);
vector<int> a({1,2,3})
v.front() / v.back(); v.push_back(data) / v.emplace_back(data) / v.pop_back(); v.insert(iterator, data) / v.erase(iterator) / v.erase(first, last); // 下标 -> 迭代器:v.begin() + index; // 迭代器 -> 下标:it - v.begin();
五、string
//1.
string str1; //生成空字符串
//2.
string str2("123456789"); //生成"1234456789"的复制品
//3.
string str3("12345", 0, 3);//结果为"123" ,从0位置开始,长度为3
//4.
string str4("123456", 5); //结果为"12345" ,长度为5
//5.
string str5(5, '2'); //结果为"22222" ,构造5个字符'2'连接而成的字符串
//6.
string str6(str2, 2); //结果为"3456789",截取第三个元素(2对应第三位)到最后
// 支持比较运算符:<、<=、>、>=、==、!=;会按字典顺序进行比较;
// 支持 + 运算符:可以进行字符串拼接;
// 新增插入
s.append(str);
// 新增删除
s.erase(ite, len);
// 新增类型转换
stoi(s), stoll(s), stod(s), stold(s);
// 新增分割
s.substr(ite, n);
// 新增查找
s.find("abc"); 返回位置索引,没找到返回 -1;
s.find(char, pos) 例:s.find('i',6);
六、deque:可用 sort 排序
d.push_back(ele)、d.push_front(ele)将元素 ele插入队尾、队首 d.pop_back()、d.pop_front()将队尾元素删除、将队首元素删除 d.front()返回队首元素 d.back()返回队尾元素
七、stack:不可以用 sort 排序
s.push(ele); s.pop(); s.top();
八、 queue:不可用 sort 排序
q.push(ele); q.pop(); q.front(); q.back();
九、priority_queue 优先队列:没有 clear 方法
priority_queue<int> q1; // 默认大根堆, 即每次取出的元素是队列中的最大值 priority_queue<int, vector<int>, less<int> > q2; // 大根堆, 每次取出的元素是队列中的最大值,同第一行 priority_queue<int, vector<int>, greater<int> > q3; // 小根堆, 每次取出的元素是队列中的最小值
p.push(ele); p.pop(); p.top();
十、map(查找效率 O(log n))
mp.erase(it) / mp.erase(key);
mp.insert({key, value});
mp.find(key); // 返回迭代器
mp.count(key); // 返回 0 或 1
十一、set
与 map 用法一样
十二、pair 二元组
//头文件
#include<utility>
//1.初始化定义
pair<string, int> p("wangyaqi",1);//带初始值的
pair<string, int> p;//不带初始值的
//2.赋值
p = {"wang", 18};
p = make_pair("wang", 18);
p = pair<string, int>("wang", 18);
//定义结构体数组
pair<int,int> p[20];
for(int i = 0; i < 20; i++) {
//和结构体类似,first代表第一个元素,second代表第二个元素
cout << p[i].first << " " << p[i].second;
}
十三、STL 中 map 与 unordered_map 有什么区别?
- map 底层是红黑树实现的;unordered_map 是哈希表实现的。
- map 遍历出来是有序的;unordered_map 遍历出来是无序的。
- 当不需要结果排好序时,最好用unordered_map,插入删除和查询的效率要高于map。
十四、vector 与 list 差异?
vector 是动态数组,是一个连续的内存快,随机访问是 O(1) 复杂度,迭代器支持随机访问。
list 是双向链表,是离散的内存,随机访问是 O(n) 复杂度,迭代器仅支持 ++/--
十五、STL 里 resize 和 reserve 的区别是什么?
resize 只是改变当前容器的长度;reserve 改变的是当前容器最大容量,最多可以放多少元素。
十六、STL 中迭代器有什么作用?有指针为何还要迭代器?
1)可以统一不同容器的访问接口。
2)支持算法复用,如:sort、find 等。
3)封装层次高,不需要了解容器的具体实现方式就可以访问容器元素。
迭代器不是指针,而是类模板,本质上封装了指针,为的就是把不同容器类的访问逻辑进行抽象和统一。
十七、map 和 set 有什么区别?分别是怎么实现的?
map 和 set 都是关联容器,底层实现都是红黑树。
区别:
map 中的元素是键值对;set 中的是关键字集合,元素不能重复。
map 允许修改 value,不能改 key;set 的迭代器是 const,不允许修改元素的值。原因:红黑树会根据键的大小组织节点,如果直接修改键会打破有序性,进而破坏红黑树的结构,导致后续无法正常操作。
map 支持下标操作(用 key 做下标);set 不支持下标操作。
十八、删除迭代器影响
vector、deque(queue 不提供迭代器)、array:会使当前迭代器及其后所有迭代器失效。
list、forward_list、map、set、multimap、multiset:只会使当前迭代器失效。
十九、为什么 stl 里面有 sort 函数,list 里面还要再定义一个 sort?
因为 sort 需要随机访问迭代器,而 list 只提供双向迭代器。
二十、deque 实现
数据在多个块存储,但块之间不连续。(分块存储)
有一个指针数组,分别指向每个内存快。
还有一个块内指针,指向块内的元素。
一名985硕,在25年秋招中斩获多个C++/嵌入式开发Offer。本专栏将分享我的面经,涵盖C/C++、操作系统、计算机网络、ARM体系与架构、Linux应用/驱动开发、Qt、通信协议及开发工具链等核心内容。
