一、容器的分类与结构
在 C++ 标准模板库(STL)中,容器(Containers)是用于存储和管理数据的重要组件。根据数据的组织方式和访问特性,容器可以分为以下几类:
-
序列容器(Sequence Containers):
- Array:固定大小的数组,元素在内存中连续存储。
- Vector:动态数组,可以自动调整大小,支持随机访问。
- Deque:双端队列,支持在两端进行插入和删除操作。
- List:双向链表,支持在任意位置进行插入和删除操作。
- Forward-List:单向链表,支持在任意位置进行插入和删除操作,但只能单向遍历。
-
关联容器(Associative Containers):
- Set/Multiset:集合,存储唯一的键值,按键值排序。
- Map/Multimap:映射,存储键值对,按键值排序。
-
无序容器(Unordered Containers):
- Unordered Set/Multiset:无序集合,存储唯一的键值,不按键值排序。
- Unordered Map/Multimap:无序映射,存储键值对,不按键值排序。
二、容器的内部结构
-
序列容器:
- Array:固定大小的数组,元素在内存中连续存储。
- Vector:动态数组,内部使用连续的内存空间,通过指针和容量管理来实现动态调整。
- Deque:双端队列,内部使用多个连续的内存块,支持在两端进行插入和删除操作。
- List:双向链表,每个节点包含数据和前后指针,支持在任意位置进行插入和删除操作。
- Forward-List:单向链表,每个节点包含数据和后指针,支持在任意位置进行插入和删除操作,但只能单向遍历。
-
关联容器:
- Set/Multiset:内部使用平衡二叉搜索树(如红黑树),按键值排序,支持快速的查找、插入和删除操作。
- Map/Multimap:内部使用平衡二叉搜索树,按键值排序,支持快速的查找、插入和删除操作,存储键值对。
-
无序容器:
- Unordered Set/Multiset:内部使用哈希表,通过哈希函数将键值映射到哈希表的槽位,支持快速的查找、插入和删除操作。
- Unordered Map/Multimap:内部使用哈希表,通过哈希函数将键值映射到哈希表的槽位,支持快速的查找、插入和删除操作,存储键值对。
三、测试案例代码
1. 序列容器测试案例
Vector 测试案例:
#include <iostream>
#include <vector>int main() {std::vector<int> vec;// 添加元素vec.push_back(10);vec.push_back(20);vec.push_back(30);// 访问元素std::cout << "vec[0]: " << vec[0] << std::endl;std::cout << "vec[1]: " << vec[1] << std::endl;std::cout << "vec[2]: " << vec[2] << std::endl;// 删除元素vec.erase(vec.begin() + 1);// 遍历for (int i : vec) {std::cout << i << " ";}return 0;
}
List 测试案例:
#include <iostream>
#include <list>int main() {std::list<int> lst;// 添加元素lst.push_back(10);lst.push_front(20);// 删除元素lst.remove(10);// 遍历for (int i : lst) {std::cout << i << " ";}return 0;
}
2. 关联容器测试案例
Set 测试案例:
#include <iostream>
#include <set>int main() {std::set<int> s;// 插入元素s.insert(10);s.insert(20);s.insert(30);// 查找元素auto it = s.find(20);if (it != s.end()) {std::cout << "Found: " << *it << std::endl;}// 删除元素s.erase(20);// 遍历for (int i : s) {std::cout << i << " ";}return 0;
}
Map 测试案例:
#include <iostream>
#include <map>int main() {std::map<int, std::string> m;// 插入键值对m[1] = "one";m[2] = "two";m[3] = "three";// 查找键值对auto it = m.find(2);if (it != m.end()) {std::cout << "Found: " << it->first << " -> " << it->second << std::endl;}// 删除键值对m.erase(2);// 遍历for (auto const& pair : m) {std::cout << pair.first << " -> " << pair.second << std::endl;}return 0;
}
3. 无序容器测试案例
Unordered Set 测试案例:
#include <iostream>
#include <unordered_set>int main() {std::unordered_set<int> us;// 插入元素us.insert(10);us.insert(20);us.insert(30);// 查找元素auto it = us.find(20);if (it != us.end()) {std::cout << "Found: " << *it << std::endl;}// 删除元素us.erase(20);// 遍历for (int i : us) {std::cout << i << " ";}return 0;
}
Unordered Map 测试案例:
#include <iostream>
#include <unordered_map>int main() {std::unordered_map<int, std::string> um;// 插入键值对um[1] = "one";um[2] = "two";um[3] = "three";// 查找键值对auto it = um.find(2);if (it != um.end()) {std::cout << "Found: " << it->first << " -> " << it->second << std::endl;}// 删除键值对um.erase(2);// 遍历for (auto const& pair : um) {std::cout << pair.first << " -> " << pair.second << std::endl;}return 0;
}
四、学习心得
通过学习,我对 STL 容器的结构与分类有了更深入的理解。掌握了STL 容器的核心概念和应用技巧。特别是通过实际的测试案例代码,我更好地理解了每种容器的特性和使用方法。
在实际编程中,合理选择和使用 STL 容器可以显著提高代码的可读性和可维护性。例如,对于需要频繁插入和删除操作的场景,可以选择 list
或 forward_list
;对于需要快速查找和排序的场景,可以选择 set
或 map
;对于需要快速查找但不关心顺序的场景,可以选择 unordered_set
或 unordered_map
。
在未来的学习和工作中,我将继续深入探索 STL 容器的高级特性,并将其应用到实际项目中,以提升自己的编程能力。