📌 相关文章推荐
很高兴你点开这篇文章✨
这里会持续更新我喜欢的内容,关注我,一起慢慢变好呀
👍 点赞 ⭐ 收藏 💬 评论
文章目录
前言
你有没有这种感觉:学完C++的类和模板之后,突然发现自己好像什么都能写了——Stack、Queue、Date、顺序表……但是写完之后又会想:我写的这个有没有bug?扩容策略对不对?拷贝构造有没有深拷贝?
- 其实这些轮子,C++标准库已经帮我们造好了
- 这就是STL(Standard Template Library,标准模板库)
STL是C++标准库的核心组成部分,它提供了我们日常开发中最常用的数据结构和算法。不需要我们自己写链表、动态数组、平衡树,直接用就行。
🐶 🐾 ✨ 🐾 🐶
一、STL的六大组件
STL由六个部分组成:
| 组件 | 作用 | 例子 |
|---|---|---|
| 容器 | 存数据的东西 | vector、list、map、set |
| 算法 | 对数据进行操作 | sort、find、reverse |
| 迭代器 | 遍历容器的工具 | begin()、end() |
| 仿函数 | 行为像函数的对象 | less、greater |
| 适配器 | 改造容器的接口 | stack、queue |
| 分配器 | 管理内存 | allocator |
🐶 🐾 ✨ 🐾 🐶
二、最常用的容器:vector
2.1 vector是什么
vector就是一个能自动扩容的动态数组。
2.2 基本用法
#include <vector>
#include <iostream>
using namespace std;
int main()
{
// 创建vector
vector<int> v1; // 空的
vector<int> v2(5, 0); // 5个0
vector<int> v3 = {1,2,3,4,5}; // 初始化为1,2,3,4,5
// 尾部插入
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
// 访问元素
cout << v1[0] << endl; // 下标访问,不检查越界
cout << v1.at(0) << endl; // 带边界检查
// 获取大小和容量
cout << v1.size() << endl; // 实际元素个数:3
cout << v1.capacity() << endl; // 当前容量
// 遍历
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
// 删除最后一个元素
v1.pop_back();
// 清空
v1.clear();
return 0;
}
2.3 我们需要注意的点
vector的扩容一般是翻倍扩容size()是实际元素个数,capacity()是已分配空间大小频繁的push_back可能会导致多次扩容,如果知道要存多少数据,可以先reserve预留空间
vector<int> v;
v.reserve(100); // 提前预留100个位置,避免多次扩容
for (int i = 0; i < 100; i++)
{
v.push_back(i);
}
🐶 🐾 ✨ 🐾 🐶
三、迭代器:连接容器和算法的桥梁
3.1 迭代器是什么
可以把迭代器理解成一个能遍历容器的指针。不同容器的内部结构不一样(数组、链表、树),但迭代器提供了一个统一的访问方式。
3.2 基本用法
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5};
// 使用迭代器遍历
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
it++;
}
cout << endl;
// C++11之后可以用auto简化
for (auto it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
// 范围for(底层也是用迭代器)
for (int x : v)
{
cout << x << " ";
}
cout << endl;
return 0;
}
3.3 迭代器的种类
| 类型 | 特点 | 适用容器 |
|---|---|---|
| 输入迭代器 | 只读,只能向前 | istream_iterator |
| 输出迭代器 | 只写,只能向前 | ostream_iterator |
| 前向迭代器 | 读写,只能向前 | forward_list |
| 双向迭代器 | 读写,可前可后 | list、set、map |
| 随机访问迭代器 | 读写,支持it+n | vector、deque、array |
vector的迭代器是最高级的随机访问迭代器,list的是双向迭代器。
🐶 🐾 ✨ 🐾 🐶
四、常用算法:不用自己写排序了
STL提供了大量算法,在头文件里。
4.1 sort排序
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
vector<int> v = {5, 2, 8, 1, 9, 3};
// 从小到大排序
sort(v.begin(), v.end());
for (int x : v)
{
cout << x << " "; // 1 2 3 5 8 9
}
cout << endl;
// 从大到小排序
sort(v.begin(), v.end(), greater<int>());
for (int x : v)
{
cout << x << " "; // 9 8 5 3 2 1
}
cout << endl;
return 0;
}
4.2 find查找
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5};
auto it = find(v.begin(), v.end(), 3);
if (it != v.end())
{
cout << "找到了:" << *it << endl;
}
else
{
cout << "没找到" << endl;
}
return 0;
}
4.3 其他常用算法
| 算法 | 作用 | 示例 |
|---|---|---|
| reverse | 反转 | reverse(v.begin(), v.end()) |
| max/min | 取最大值/最小值 | max(a, b) |
| swap | 交换 | swap(a, b) |
| count | 计数 | count(v.begin(), v.end(), 3) |
| copy | 复制 | copy(src.begin(), src.end(), dest.begin()) |
🐶 🐾 ✨ 🐾 🐶
五、另一个常用容器:list
list就是双向链表。和vector的区别:
| 对比 | vector | list |
|---|---|---|
| 底层 | 动态数组 | 双向链表 |
| 随机访问 | O(1) | O(n) |
| 中间插入/删除 | O(n)(要移动元素) | O(1) |
| 内存 | 连续内存 | 不连续,需要额外指针 |
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lst = {1, 2, 3, 4, 5};
// 头部插入
lst.push_front(0);
// 尾部插入
lst.push_back(6);
// 遍历(list迭代器不支持 + 操作,只能用++或--)
for (auto it = lst.begin(); it != lst.end(); it++)
{
cout << *it << " ";
}
cout << endl; // 0 1 2 3 4 5 6
return 0;
}
🐾 什么时候用list?
当你需要在中间频繁插入删除、不关心随机访问的时候。不然直接用vector更简单。
🐶 🐾 ✨ 🐾 🐶
六、关联容器:map和set
6.1 map:键值对
map像是一个字典,存的是<key, value>对。key是唯一的,底层是红黑树
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
// 创建map
map<string, int> scores;
// 插入
scores["小明"] = 90;
scores["小红"] = 85;
scores.insert({"小刚", 88});
// 访问
cout << scores["小明"] << endl; // 90
// 查找
if (scores.find("小明") != scores.end())
{
cout << "找到了" << endl;
}
// 遍历
for (auto& p : scores)
{
cout << p.first << ":" << p.second << endl;
}
return 0;
}
6.2 set:集合
set存的是不重复的元素,底层也是红黑树
#include <set>
#include <iostream>
using namespace std;
int main()
{
set<int> s;
s.insert(3);
s.insert(1);
s.insert(5);
s.insert(3); // 重复的不会插入
for (int x : s)
{
cout << x << " "; // 1 3 5(自动排序)
}
cout << endl;
// 查找
if (s.find(3) != s.end())
{
cout << "3在集合中" << endl;
}
return 0;
}
🐶 🐾 ✨ 🐾 🐶
七、适配器:stack和queue
set存的是不重复的元素,底层也是红黑树 x
7.1 stack
#include <stack>
#include <iostream>
using namespace std;
int main()
{
stack<int> st;
st.push(1);
st.push(2);
st.push(3);
while (!st.empty())
{
cout << st.top() << " ";
st.pop();
}
cout << endl; // 3 2 1
return 0;
}
7.2 queue
#include <queue>
#include <iostream>
using namespace std;
int main()
{
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
while (!q.empty())
{
cout << q.front() << " ";
q.pop();
}
cout << endl; // 1 2 3
return 0;
}
🐶 🐾 ✨ 🐾 🐶
八、总结
STL很大,我们不需要一次全学完。但下面这几个是最常用的:
| 容器 | 什么时候用 |
|---|---|
| vector | 绝大多数情况,动态数组首选 |
| list | 需要中间频繁插入删除 |
| map | 需要键值对映射 |
| set | 需要去重+自动排序 |
| stack/queue | 需要栈或队列功能 |
🐾 !!!学STL最好的方式就是自己写代码跑一跑。不用急着背接口,用到了查文档就行。
🐶 🐾 ✨ 🐾 🐶
- 欢迎留言交流
- 期待你的评论与建议
- 留下你的想法吧
谢谢你看到这里呀
如果喜欢这篇内容,点个关注,下次更新不迷路✨
👍 点赞 ⭐ 收藏 💬 评论

6073

被折叠的 条评论
为什么被折叠?



