C++ 学习 —— 04 - STL容器
目录
一、STL概述
二、STL容器
2.1 顺序容器
2.1.1 顺序容器简介
2.1.2 array
2.1.3 vector
2.1.4 deque
2.1.5 list
2.2 关联容器
2.2.1 关联容器简介
2.2.2 set
2.2.3 map
2.3 容器适配器
2.3.1 stack(栈)
2.3.2 queue(队列)
一、STL概述
C++ STL(Standard Template Library,标准模板库)是 C++ 标准库中用于管理和存储数据集合的一组模板类。STL 提供了常用的数据结构(如数组、链表、队列、栈、集合、映射等)和算法,极大地提高了 C++ 开发的效率和代码的通用性。
二、STL容器
2.1 顺序容器
2.1.1 顺序容器简介

2.1.2 array

- array 可以理解为静态数组,不能动态扩容或缩减。
 - 内存连续,支持高效随机访问。
 - array 容器元数据(如大小、容量、指向实际数据的指针)存放在栈中,实际存储元素也存放在栈中。
 
#include <iostream>
#include <array>
#include <algorithm> // sortusing namespace std;int main() {// 1. 定义 arrayarray<int, 5> arr = { 1, 2, 3, 4, 5 };// 2. 访问元素cout << arr[0] << endl;    // 1cout << arr.at(1) << endl; // 2  at()会检查越界cout << arr.front() << endl; // 1  // front() 返回首个元素cout << arr.back() << endl;  // 5  // back() 返回最后元素// 3. size() 获取已存放元素个数cout << arr.size() << endl;  // 5// 4. 遍历for (int i = 0; i < arr.size(); i++) {  // 当然我们也可以用基于范围的 for 循环cout << arr[i] << " ";  // 1 2 3 4 5}cout << endl;// 5. fill() 将 array 所有元素填充为指定元素arr.fill(10);  // 10 10 10 10 10// 6. swap() 交换两个 array 中的元素array<int, 5> arr1 = { 10,20,30,40,50 };arr.swap(arr1);// 7. data() 获取 array 指针int* p = arr.data();for (int i = 0; i < arr.size(); i++) {cout << p[i] << " ";  // 10 20 30 40 50}cout << endl;for (int i = 0; i < arr.size(); i++) {cout << *(p + i) << " ";  // 10 20 30 40 50}cout << endl;// 8. 使用迭代器遍历 // begin() 返回容器第一个元素的迭代器(可以理解为指针)  end() 返回容器最后一个元素(下一个位置)的迭代器(可以理解为指针) it++:向容器后面移动for (auto it = arr.begin(); it != arr.end(); it++) { cout << *it << " ";  // 10 20 30 40 50}cout << endl;// 使用反向迭代器遍历 // rbegin() 返回容器最后第一元素的迭代器(可以理解为指针)  rend() 返回容器第一个元素(上一个位置)的迭代器(可以理解为指针) rit++:向容器前面移动for (auto rit = arr.rbegin(); rit != arr.rend(); rit++) {cout << *rit << " ";  // 50 40 30 20 10}cout << endl;// 9. sort排序array<int, 5> arr2 = { 10,50,20,6,5 };sort(arr2.begin(), arr2.end()); // 5 6 10 20 50// 10. reverse() 逆置reverse(arr2.begin(), arr2.end()); // 50 20 10 6 5return 0;
}
 
2.1.3 vector

- vector 可以理解为动态数组的另一种实现方式,可以动态扩容和缩减。且对尾部的插入删除速度相对较快。
 - 内存连续,支持高效随机访问。
 - vector 容器元数据(如大小、容量、指向实际数据的指针)存放在栈中,实际存储元素存放在堆中。
 
注意:vector 在动态扩容时,并不是在原空间之后续接新空间,而是寻找更大的内存空间,将原数据拷贝到新空间中,然后释放原空间。
#include <iostream>
#include <vector>
#include <algorithm> // sort, reverseusing namespace std;int main() {// 1. 定义 vectorvector<int> v1;          // 空 vectorvector<int> v2(5);       // 0 0 0 0 0vector<int> v3(5, 10);   // 10 10 10 10 10vector<int> v4 = { 1,2,3,4,5 };  // 1 2 3 4 5vector<int> v5(v4);      // 1 2 3 4 5  (拷贝构造)// 2. 访问元素cout << v4[0] << endl;     // 1cout << v4.at(1) << endl;  // 2cout << v4.front() << endl; // 1cout << v4.back() << endl;  // 5// 3. size() 获取已存放元素个数  capacity() 获取已分配的空间容量cout << v4.size() << endl;  // 5cout << v4.capacity() << endl;  // 5v4.reserve(100); // // 预留空间cout << v4.capacity() << endl;  // 100// 4. 遍历for (int i = 0; i < v4.size(); i++) {cout << v4[i] << " ";  // 1 2 3 4 5 }cout << endl;// 5. 尾部插入元素  尾部删除元素v4.push_back(6); // 1 2 3 4 5 6v4.pop_back();   // 1 2 3 4 5// 6. 插入元素 删除元素v4.insert(v4.begin(), 0); // 在位置 0 处插入元素 0             0 1 2 3 4 5 v4.insert(v4.begin() + 2, 999);  // 在位置 2 处插入元素 999    0 1 999 2 3 4 5 v4.insert(v4.end(), 6); // 在末尾插入元素 6                    0 1 999 2 3 4 5 6v4.erase(v4.begin()); // 删除位置 0 处的元素                   1 999 2 3 4 5 6v4.erase(v4.begin(), v4.begin() + 2); // 删除范围[0,2)              2 3 4 5 6// 7. swap() 交换两个 vector 中的元素v4.swap(v5);// 8. data() 获取 vector 指针int* p = v4.data();for (int i = 0; i < v4.size(); i++) {cout << p[i] << " ";  // 1 2 3 4 5}cout << endl;for (int i = 0; i < v4.size(); i++) {cout << *(p + i) << " ";  // 1 2 3 4 5}cout << endl;// 9. 使用迭代器遍历 for (auto it = v4.begin(); it != v4.end(); it++) {cout << *it << " ";  // 1 2 3 4 5}cout << endl;// 使用反向迭代器遍历 for (auto rit = v4.rbegin(); rit != v4.rend(); rit++) {cout << *rit << " ";  // 5 4 3 2 1}cout << endl;// 9. sort排序sort(v4.begin(), v4.end()); // 1 2 3 4 5// 10. reverse() 逆置reverse(v4.begin(), v4.end()); // 5 4 3 2 1return 0;
}
 
2.1.4 deque

- 相比于 vector,deque 对头部的插入删除速度相对较快。
 - 内存分块管理,支持随机访问。
 - deque 容器元数据(如大小、容量、指向实际数据的指针)存放在栈中,实际存储元素存放在堆中。
 
#include <iostream>
#include <deque>
#include <algorithm> // sort, reverseusing namespace std;int main() {// 1. 定义 dequedeque<int> d1;          // 空 dequedeque<int> d2(5);       // 0 0 0 0 0deque<int> d3(5, 10);   // 10 10 10 10 10deque<int> d4 = { 1,2,3,4,5 };  // 1 2 3 4 5deque<int> d5(d4);      // 1 2 3 4 5  (拷贝构造)// 2. 访问元素cout << d4[0] << endl;     // 1cout << d4.at(1) << endl;  // 2cout << d4.front() << endl; // 1cout << d4.back() << endl;  // 5// 3. size() 获取已存放元素个数   注意: deque 没有 capacity() 和 data() 方法, 因为其内存空间不是连续的cout << d4.size() << endl;  // 5// 4. 遍历for (int i = 0; i < d4.size(); i++) {cout << d4[i] << " ";  // 1 2 3 4 5 }cout << endl;// 5. 尾部插入元素  尾部删除元素d4.push_back(6); // 1 2 3 4 5 6d4.pop_back();   // 1 2 3 4 5// 6. 头部插入元素 头部删除元素d4.push_front(0); // 0 1 2 3 4 5d4.pop_front();   // 1 2 3 4 5// 7. 插入元素 删除元素d4.insert(d4.begin(), 0); // 在位置 0 处插入元素 0             0 1 2 3 4 5 d4.insert(d4.begin() + 2, 999);  // 在位置 2 处插入元素 999    0 1 999 2 3 4 5 d4.insert(d4.end(), 6); // 在末尾插入元素 6                    0 1 999 2 3 4 5 6d4.erase(d4.begin()); // 删除位置 0 处的元素                   1 999 2 3 4 5 6d4.erase(d4.begin(), d4.begin() + 2); // 删除范围[0,2)              2 3 4 5 6// 8. swap() 交换两个 deque 中的元素d4.swap(d5);// 9. 使用迭代器遍历 for (auto it = d4.begin(); it != d4.end(); it++) {cout << *it << " ";  // 1 2 3 4 5}cout << endl;// 使用反向迭代器遍历 for (auto rit = d4.rbegin(); rit != d4.rend(); rit++) {cout << *rit << " ";  // 5 4 3 2 1}cout << endl;// 9. sort排序sort(d4.begin(), d4.end()); // 1 2 3 4 5// 10. reverse() 逆置reverse(d4.begin(), d4.end()); // 5 4 3 2 1return 0;
}
 
2.1.5 list

- 插入/删除效率高(任何位置),但随机访问慢。
 - 内存分散,占用空间较大(需额外存储前后指针)。
 - list 容器元数据(如大小、容量、指向实际数据的指针)存放在栈中,实际存储元素存放在堆中。
 
#include <iostream>
#include <list>
#include <algorithm> // sort, reverseusing namespace std;int main() {// 1. 定义 listlist<int> l1;            // 空 listlist<int> l2(5);         // 5 个元素,默认值 0list<int> l3(5, 10);     // 5 个元素,值为 10list<int> l4 = { 1, 2, 3, 4, 5 }; // 列表初始化list<int> l5(l4);        // 拷贝构造// 2. 访问元素cout << l4.front() << endl; // 1cout << l4.back() << endl;  // 5// 注意:list 不支持 operator[] 或 at(),因为它不是随机访问容器// 3. size() cout << l4.size() << endl;   // 5// 4. 迭代器遍历for (auto it = l4.begin(); it != l4.end(); ++it) {cout << *it << " ";  // 1 2 3 4 5}cout << endl;// 5. 尾部插入/删除l4.push_back(6);  // 1 2 3 4 5 6l4.pop_back();    // 1 2 3 4 5// 6. 头部插入/删除l4.push_front(0); // 0 1 2 3 4 5l4.pop_front();   // 1 2 3 4 5// 7. 插入元素 删除元素auto it = l4.begin();advance(it, 2);  // 将迭代器移动到第 2 个位置l4.insert(it, 999); // 1 2 999 3 4 5it = l4.begin();advance(it, 2);l4.erase(it); // 1 2 3 4 5// 8. 删除所有满足条件的元素l4.remove(3); // 1 2 4 5// 9. swap()l4.swap(l5);  // 1 2 3 4 5// 10. sort排序l4.sort(); // 1 2 3 4 5// 11. reverse 反转l4.reverse(); // 5 4 3 2 1// 12. unique 删除相邻重复元素list<int> l6 = { 1,1,2,2,2,3,3,4 };l6.unique(); // 1 2 3 4return 0;
}
 
 
2.2 关联容器
2.2.1 关联容器简介
关联式容器以平衡二叉搜索树(标准实现通常为红黑树) 为底层结构,元素按“键”排序,查找、插入、删除均为 O(log n)。
2.2.2 set
- 所有元素在插入时自动被排序。
 - 不允许有重复元素。
 
#include <iostream>
#include <set>
using namespace std;int main() {// 1. 定义 setset<int> s1;                  // 空 setset<int> s2 = { 5, 3, 1, 4, 2 }; // 1 2 3 4 5set<int> s3(s2);              // 1 2 3 4 5// 2. size()cout << s2.size() << endl;  // 5// 3. 迭代器遍历 for (auto it = s2.begin(); it != s2.end(); ++it) {cout << *it << " ";  // 1 2 3 4 5}cout << endl;// 4. 插入元素 删除元素s2.insert(10); // 1 2 3 4 5 10s2.erase(5); // 1 2 3 4 10// 5. 查找元素 // find()   如果找到则返回该元素的迭代器,如果没有找到则返回 end()// count()  如果找到则返回 1,如果没有找到则返回 0auto it = s2.find(3); if (it != s2.end()) cout << "找到了" << endl;cout << s2.count(3) << endl; // 1 // 6. swap()set<int> s4 = { 1,2,3 };s2.swap(s4);  // 1 2 3return 0;
}
 
2.2.3 map
- map 中所有元素都是 pair。pair 中第一个元素为 key(键值),起到索引作用,第二个元素为 value(实值)
 - 所有元素在插入时自动被排序。
 - 不允许有重复元素(key)。
 
#include <iostream>
#include <map>
#include <string>
using namespace std;int main() {// 1️. 定义 mapmap<int, string> m1; // 空 mapmap<int, string> m2 = { {1, "apple"}, {2, "banana"}, {3, "cherry"} };// 2. 迭代器遍历for (auto it = m2.begin(); it != m2.end(); ++it)cout << it->first << " : " << it->second << endl;// 3. 插入元素m1.insert({ 1, "cat" });m1.insert(make_pair(2, "dog"));m1[3] = "bird";   // 若存在则修改,不存在则创建m1[4] = "fish";m1.emplace(5, "tiger"); // 原地构造// 4. 删除元素m1.erase(1);                // 按 key 删除m1.erase(m1.begin());       // 按迭代器删除// 5. 查找auto it = m1.find(3);if (it != m1.end()) cout << "找到了" << endl;cout << m1.count(3) << endl; // 1// 6. swap()m1.swap(m2);return 0;
} 
2.3 容器适配器
2.3.1 stack(栈)
后进先出,底层一般用 deque 实现。
2.3.2 queue(队列)
先进先出,底层一般用 deque 实现。
