【C++】标准模板库STL-容器
STL 容器是其中的重要组成部分,它们可以存储、组织和操作数据集合。以下是一些常用的 STL 容器:
1. 向量(std::vector)
一个动态数组,支持快速随机访问。它可以根据需要自动调整大小,适合需要频繁插入和删除的场景。
在C++中,std::vector 是标准模板库(STL)中的一个非常常用的容器,它提供了动态数组的功能。std::vector 可以存储任意类型的元素,并且可以根据需要自动调整大小以容纳更多元素。
1.1. 特性
- 动态数组:
std::vector可以根据元素数量动态调整其存储空间。 - 随机访问:它提供了对元素的快速随机访问,允许通过索引直接访问元素。
- 类型安全:只能存储指定类型的元素。
- 内存管理:自动管理内存,当元素被添加或删除时,
std::vector会自动分配或释放内存。
1.2. 基本操作
- 添加元素:
push_back():在容器尾部添加一个元素。emplace_back():在容器尾部构造一个元素(使用位置参数)。
- 访问元素:
- 使用下标操作符
operator[]来访问或修改元素。 at():提供对元素的安全访问,并会检查索引是否越界。
- 删除元素:
pop_back():移除容器尾部的元素。erase():移除指定位置的元素或范围。
- 大小和容量:
size():返回容器中元素的数量。empty():检查容器是否为空。capacity():返回分配给容器的内存,以容纳其元素。
- 清空容器:
clear():移除容器中的所有元素。
- 遍历:
- 使用迭代器通过
begin()和end()成员函数来遍历容器。
- 排序:
std::sort():可以对std::vector中的元素进行排序。
1.3. 示例代码
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 5 int main() { 6 // 创建 vector 7 std::vector<int> vec; 8 9 // 添加元素到 vector 10 vec.push_back(10); 11 vec.push_back(20); 12 vec.push_back(30); 13 vec.push_back(5); // 插入到末尾 14 15 // 使用 emplace_back 构造元素 16 vec.emplace_back(40); 17 18 // 访问元素 19 int firstElement = vec.front(); // 获取第一个元素 20 int lastElement = vec.back(); // 获取最后一个元素 21 std::cout << "First element: " << firstElement << std::endl; 22 std::cout << "Last element: " << lastElement << std::endl; 23 24 // 删除 vector 的最后一个元素 25 vec.pop_back(); 26 27 // 遍历 vector 28 std::cout << "Vector contents: "; 29 for (int elem : vec) { 30 std::cout << elem << " "; 31 } 32 std::cout << std::endl; 33 34 // 检查 vector 是否为空 35 if (!vec.empty()) { 36 std::cout << "The vector is not empty." << std::endl; 37 } 38 else { 39 std::cout << "The vector is empty." << std::endl; 40 } 41 42 // 获取 vector 的大小 43 std::cout << "Size of vector: " << vec.size() << std::endl; 44 45 // 使用迭代器 46 std::vector<int>::iterator it; 47 it = vec.begin(); // it 现在指向 vector 的第一个元素 48 49 // 删除特定位置的元素 50 it = vec.erase(it); // 假设 it 指向要删除的元素 51 52 // 排序 vector 53 std::vector<int> sortedVec = vec; // 假设 vec 有元素 54 std::sort(sortedVec.begin(), sortedVec.end()); 55 56 // 清空 vector 57 vec.clear(); 58 if (vec.empty()) { 59 std::cout << "Vector cleared." << std::endl; 60 } 61 62 return 0; 63 }
2. 双端队列(std::deque)
在C++中,std::deque(双端队列)是一种允许在两端进行高效插入和删除操作的容器。它通常用于需要在序列两端频繁添加或删除元素的场景。以下是 std::deque 的一些基本特性和操作:
2.1. 特性
- 两端操作:可以在队列的两端快速地添加或删除元素。
- 动态大小:
std::deque的大小可以根据元素数量动态变化。 - 非连续存储:与
std::vector不同,std::deque的元素存储在非连续的内存块中,这使得中间位置的插入和删除操作效率较低。
2.2. 基本操作
- 添加元素:
push_back():在容器尾部添加一个元素。push_front():在容器头部添加一个元素。
- 访问元素:
- 使用下标操作符
operator[]或at()来访问或修改元素。
- 删除元素:
pop_back():移除容器尾部的元素。pop_front():移除容器头部的元素。erase():移除指定位置的元素或范围。
- 大小和容量:
size():返回容器中元素的数量。empty():检查容器是否为空。
- 清空容器:
clear():移除容器中的所有元素。
- 遍历:
- 使用迭代器通过
begin()和end()成员函数来遍历容器。
2.3. 示例代码
1 #include <iostream> 2 #include <deque> 3 4 int main() { 5 // 创建 deque 6 std::deque<int> dq; 7 8 // 添加元素到 deque 9 dq.push_back(10); // 在尾部添加 10 dq.push_back(20); // 在尾部添加 11 dq.push_back(30); // 在尾部添加 12 dq.push_front(40); // 在头部添加 13 14 // 访问元素 15 std::cout << "Front element: " << dq.front() << std::endl; // 访问头部元素 16 std::cout << "Back element: " << dq.back() << std::endl; // 访问尾部元素 17 18 // 删除元素 19 dq.pop_front(); // 删除头部元素 20 dq.pop_back(); // 删除尾部元素 21 22 // 遍历 deque 23 std::cout << "Deque elements: "; 24 for (int elem : dq) { 25 std::cout << elem << " "; 26 } 27 std::cout << std::endl; 28 29 // 检查 deque 是否为空 30 if (dq.empty()) { 31 std::cout << "The deque is empty." << std::endl; 32 } 33 else { 34 std::cout << "The deque is not empty." << std::endl; 35 } 36 37 // 获取 deque 的大小 38 std::cout << "Size of deque: " << dq.size() << std::endl; 39 40 // 删除特定位置的元素 41 auto it = dq.begin() + 1; // 获取指向特定位置的迭代器 42 dq.erase(it); // 删除该位置的元素 43 44 // 清空 deque 45 dq.clear(); 46 if (dq.empty()) { 47 std::cout << "Deque cleared." << std::endl; 48 } 49 50 return 0; 51 }
3. 列表(std::list)
在C++中,std::list是标准模板库(STL)中的一个双向链表容器。它允许在链表的任意位置高效地进行插入和删除操作,而不需要像数组那样重新分配内存。std::list 是一个有序容器,其中的元素保持它们被插入时的顺序。以下是 std::list的一些基本特性和操作:
3.1. 特性
- 双向链表:允许在链表的头部和尾部进行高效的插入和删除操作。
- 非连续存储:与
std::vector不同,std::list的元素存储在非连续的内存位置。 - 可迭代:可以双向迭代,即从头部向尾部或从尾部向头部遍历。
3.2. 基本操作
- 添加元素:
push_back():在容器尾部添加一个元素。push_front():在容器头部添加一个元素。insert():在指定迭代器位置插入一个元素。
- 访问元素:
- 使用迭代器通过
begin()和end()成员函数来访问元素。
- 删除元素:
pop_back():移除容器尾部的元素。pop_front():移除容器头部的元素。erase():移除指定位置的元素或范围。
- 大小:
size():返回容器中元素的数量。empty():检查容器是否为空。
- 清空容器:
clear():移除容器中的所有元素。
- 遍历:
- 使用迭代器通过
begin()和end()成员函数来遍历容器。
3.3. 示例代码
1 #include <iostream> 2 #include <list> 3 4 int main() { 5 std::list<int> lst; 6 7 // 添加元素到列表 8 lst.push_back(10); 9 lst.push_back(20); 10 lst.push_back(30); 11 lst.push_back(40); 12 lst.push_front(50); 13 lst.insert(lst.begin(), 60); // 在头部插入 14 15 // 访问元素 16 // std::list 没有下标操作符,必须使用迭代器 17 std::list<int>::iterator it = lst.begin(); 18 std::cout << "Element at front: " << *it << std::endl; // 获取第一个元素 19 20 // 删除元素 21 lst.pop_back(); // 删除尾部元素 22 lst.pop_front(); // 删除头部元素 23 it = lst.begin(); 24 ++it; // 移动到第二个元素 25 lst.erase(it); // 删除第二个元素 26 27 // 遍历列表 28 std::cout << "List contents: "; 29 for (int elem : lst) { 30 std::cout << elem << " "; 31 } 32 std::cout << std::endl; 33 34 // 清空列表 35 lst.clear(); 36 if (lst.empty()) { 37 std::cout << "The list is empty." << std::endl; 38 } 39 40 return 0; 41 }
4. 集合(std::set)
在C++中,std::set 是一种关联容器,它存储了一组唯一的元素,并保证这些元素处于排序状态。std::set 通常基于平衡二叉搜索树(如红黑树)实现,这使得它在添加、删除和查找操作上都能提供对数时间复杂度的性能。以下是 std::set 的一些基本特性和操作:
4.1. 特性
- 唯一性:容器中的元素值必须是唯一的。
- 有序性:元素按照升序排列,每次插入的元素都会自动被放置在正确的位置以维持排序。
- 无序访问:不支持随机访问操作,如使用下标访问元素。
4.2. 基本操作
- 添加元素:
insert():向集合中插入一个或多个元素。
- 访问元素:
- 通过迭代器访问元素,使用
begin()和end()成员函数。
- 删除元素:
erase():从集合中移除一个或多个指定位置的元素。clear():移除集合中的所有元素。
- 查找元素:
find():查找特定元素是否存在于集合中。
- 大小和空状态:
size():返回集合中元素的数量。empty():检查集合是否为空。
4.3. 示例代码
1 #include <iostream> 2 #include <set> 3 4 int main() { 5 std::set<int> mySet; 6 7 // 添加元素到集合 8 mySet.insert(10); 9 mySet.insert(20); 10 mySet.insert(30); 11 12 // 遍历集合 13 std::cout << "Set contents: "; 14 for (int num : mySet) { 15 std::cout << num << " "; 16 } 17 std::cout << std::endl; 18 19 // 查找元素 20 auto it = mySet.find(20); 21 if (it != mySet.end()) { 22 std::cout << "Element 20 found in the set." << std::endl; 23 } 24 else { 25 std::cout << "Element 20 not found in the set." << std::endl; 26 } 27 28 // 删除元素 29 mySet.erase(it); // 删除找到的元素 30 31 // 清空集合 32 mySet.clear(); 33 if (mySet.empty()) { 34 std::cout << "The set is empty." << std::endl; 35 } 36 37 return 0; 38 }
5. 多重集合(std::multiset)
在C++中,std::multiset 是 std::set 的一个变体,它允许容器中存在重复的元素。与 std::set一样,std::multiset 也保持其元素是有序的,通常基于平衡二叉搜索树实现。std::multiset 提供了与 std::set 类似的接口,但有一些关键的区别:
5.1. 特性
- 允许重复:与
std::set不同,std::multiset允许多个相同的元素。 - 有序性:元素按照升序排列,或者根据提供的比较函数排列。
- 无序访问:不支持随机访问操作。
5.2. 基本操作
- 添加元素:
insert():向多重集合中插入一个或多个元素。
- 访问元素:
- 使用迭代器通过
begin()和end()成员函数来访问元素。
- 删除元素:
erase():从多重集合中移除一个或多个指定位置的元素。clear():移除多重集合中的所有元素。
- 查找元素:
find():查找特定元素是否存在于多重集合中。count():返回多重集合中指定元素的出现次数,这是std::multiset特有的,与std::set不同。
- 大小和空状态:
size():返回多重集合中元素的总数。empty():检查多重集合是否为空。
5.3. 示例代码
1 #include <iostream> 2 #include <set> 3 4 int main() { 5 std::multiset<int> myMultiSet; 6 7 // 添加元素到多重集合 8 myMultiSet.insert(10); 9 myMultiSet.insert(10); // 允许重复 10 myMultiSet.insert(20); 11 12 // 遍历多重集合 13 std::cout << "Multiset contents: "; 14 for (int num : myMultiSet) { 15 std::cout << num << " "; 16 } 17 std::cout << std::endl; 18 19 // 查找并计数元素 20 auto it = myMultiSet.find(10); 21 if (it != myMultiSet.end()) { 22 std::cout << "Element 10 found " << myMultiSet.count(10) << " times in the multiset." << std::endl; 23 } 24 25 // 删除元素 26 myMultiSet.erase(it); // 删除找到的第一个10 27 28 // 清空多重集合 29 myMultiSet.clear(); 30 if (myMultiSet.empty()) { 31 std::cout << "The multiset is empty." << std::endl; 32 } 33 34 return 0; 35 }
6. 映射(std::map)
在C++中,std::map 是一种关联容器,它存储键值对(key-value pairs),并且每个键都是唯一的。std::map 中的元素按照键的顺序自动排序,通常是基于平衡二叉搜索树实现的,这使得它在添加、删除和查找操作上都能提供对数时间复杂度的性能。以下是 std::map 的一些基本特性和操作:
6.1. 特性
- 键的唯一性:每个键在
std::map中都是唯一的。 - 有序性:元素按照键的顺序自动排序。
- 无序访问:不支持随机访问操作,如使用下标访问元素。
6.2. 基本操作
- 添加元素:
insert():向映射中插入一个或多个键值对。
- 访问元素:
- 使用下标操作符 o
perator[]访问或修改元素(会插入键,如果键不存在)。 - 使用
at()成员函数安全地访问元素(如果键不存在,会抛出异常)。
- 删除元素:
erase():从映射中移除一个或多个指定键的元素。clear():移除映射中的所有元素。
- 查找元素:
find():查找特定键是否存在于映射中。count():返回映射中指定键的出现次数(由于键的唯一性,总是0或1)。
- 大小和空状态:
size():返回映射中元素的数量。empty():检查映射是否为空。
6.3. 示例代码
1 #include <iostream> 2 #include <map> 3 4 int main() { 5 std::map<int, std::string> myMap; 6 7 // 添加元素到映射 8 myMap.insert({ 1, "one" }); 9 myMap.insert({ 2, "two" }); 10 myMap[3] = "three"; // 使用下标操作符 11 12 // 访问元素 13 std::cout << "Element with key 2: " << myMap.at(2) << std::endl; 14 15 // 遍历映射 16 std::cout << "Map contents: "; 17 for (const auto& pair : myMap) { 18 std::cout << pair.first << ": " << pair.second << " "; 19 } 20 std::cout << std::endl; 21 22 // 查找元素 23 auto it = myMap.find(2); 24 if (it != myMap.end()) { 25 std::cout << "Key 2 is associated with value: " << it->second << std::endl; 26 } 27 28 // 删除元素 29 myMap.erase(it); // 删除找到的元素 30 31 // 清空映射 32 myMap.clear(); 33 if (myMap.empty()) { 34 std::cout << "The map is empty." << std::endl; 35 } 36 37 return 0; 38 }
7. 多重映射(std::multimap)
在C++中,std::multimap 是 std::map 的一个变体,它允许键(key)不是唯一的,即可以在映射中多次出现相同的键,每个键可以关联多个值。这与 std::map 形成对比,后者要求每个键都是唯一的。std::multimap 通常也是基于平衡二叉搜索树实现的,它保持了元素按照键的顺序自动排序。以下是 std::multimap 的一些基本特性和操作:
7.1. 特性
- 键的非唯一性:允许多个元素具有相同的键。
- 有序性:元素按照键的顺序自动排序。
- 无序访问:不支持随机访问操作。
7.2. 基本操作
- 添加元素:
insert():向多重映射中插入一个键值对。
- 访问元素:
- 使用迭代器通过
begin()和end()成员函数来访问元素。
- 删除元素:
erase():从多重映射中移除一个或多个指定键的元素,或者移除迭代器指定位置的元素。clear():移除多重映射中的所有元素。
- 查找元素:
find():查找特定键是否存在于多重映射中。count():返回多重映射中指定键的出现次数。
- 大小和空状态:
size():返回多重映射中元素的数量。empty():检查多重映射是否为空。
7.3. 示例代码
1 #include <iostream> 2 #include <map> 3 4 int main() { 5 std::multimap<int, std::string> myMultiMap; 6 7 // 添加元素到多重映射 8 myMultiMap.insert({ 1, "one" }); 9 myMultiMap.insert({ 1, "uno" }); 10 myMultiMap.insert({ 2, "two" }); 11 12 // 遍历多重映射 13 std::cout << "Multimap contents: "; 14 for (const auto& pair : myMultiMap) { 15 std::cout << pair.first << ": " << pair.second << "; "; 16 } 17 std::cout << std::endl; 18 19 // 查找元素 20 auto it = myMultiMap.find(1); 21 if (it != myMultiMap.end()) { 22 std::cout << "Key 1 is associated with values: "; 23 while (it != myMultiMap.end() && it->first == 1) { 24 std::cout << it->second << "; "; 25 ++it; 26 } 27 } 28 29 // 删除元素 30 myMultiMap.erase(1); // 删除键为1的所有元素 31 32 // 清空多重映射 33 myMultiMap.clear(); 34 if (myMultiMap.empty()) { 35 std::cout << "The multimap is empty." << std::endl; 36 } 37 38 return 0; 39 }
8. 无序集合(std::unordered_set)
在C++中,std::unordered_set 是一种关联容器,它存储了一组唯一的元素,并保证这些元素处于无序状态。与 std::set 不同,std::unordered_set 不保证元素的顺序,它的内部实现通常基于哈希表,这使得它在添加、删除和查找操作上都能提供平均常数时间复杂度的性能,但最坏情况下的时间复杂度可能是线性的。以下是 std::unordered_set 的一些基本特性和操作:
8.1. 特性
- 唯一性:容器中的元素值必须是唯一的。
- 无序性:元素的存储顺序是不确定的,它们是无序的。
- 快速查找:基于哈希表的查找操作通常非常快。
8.2. 基本操作
- 添加元素:
insert():向无序集合中插入一个或多个元素。
- 访问元素:
- 不支持随机访问,但可以通过迭代器访问元素。
- 删除元素:
erase():从无序集合中移除一个或多个指定位置的元素。clear():移除无序集合中的所有元素。
- 查找元素:
find():查找特定元素是否存在于无序集合中。
- 大小和空状态:
size():返回无序集合中元素的数量。empty():检查无序集合是否为空。
8.3. 示例代码
1 #include <iostream> 2 #include <unordered_set> 3 4 int main() { 5 std::unordered_set<int> myUnorderedSet; 6 7 // 添加元素到无序集合 8 myUnorderedSet.insert(10); 9 myUnorderedSet.insert(20); 10 myUnorderedSet.insert(30); 11 12 // 遍历无序集合 13 std::cout << "Unordered set contents: "; 14 for (int num : myUnorderedSet) { 15 std::cout << num << " "; 16 } 17 std::cout << std::endl; 18 19 // 查找元素 20 auto it = myUnorderedSet.find(20); 21 if (it != myUnorderedSet.end()) { 22 std::cout << "Element 20 found in the unordered set." << std::endl; 23 } 24 else { 25 std::cout << "Element 20 not found in the unordered set." << std::endl; 26 } 27 28 // 删除元素 29 myUnorderedSet.erase(it); // 删除找到的元素 30 31 // 清空无序集合 32 myUnorderedSet.clear(); 33 if (myUnorderedSet.empty()) { 34 std::cout << "The unordered set is empty." << std::endl; 35 } 36 37 return 0; 38 }
9. 无序多重集合(std::unordered_multiset)
在C++中,std::unordered_multiset 是一种允许存储重复元素的无序关联容器。它类似于 std::unordered_set,但是不保证元素的唯一性,即允许插入多个相同的元素。std::unordered_multiset 的内部实现通常基于哈希表,这使得它在添加、删除和查找操作上都能提供平均常数时间复杂度的性能。以下是 std::unordered_multiset 的一些基本特性和操作:
9.1. 特性
- 允许重复:可以存储相同元素的多个副本。
- 无序性:元素的存储顺序是不确定的,它们是无序的。
- 快速查找:基于哈希表的查找操作通常非常快。
9.2. 基本操作
- 添加元素:
insert():向无序多重集合中插入一个或多个元素。
- 访问元素:
- 不支持随机访问,但可以通过迭代器访问元素。
- 删除元素:
erase():从无序多重集合中移除一个或多个指定位置的元素,或者移除等于某个特定值的所有元素。clear():移除无序多重集合中的所有元素。
- 查找元素:
find():查找特定元素是否存在于无序多重集合中。count():返回无序多重集合中指定元素的出现次数。
- 大小和空状态:
size():返回无序多重集合中元素的总数。empty():检查无序多重集合是否为空。
9.3. 示例代码
1 #include <iostream> 2 #include <unordered_set> 3 4 int main() { 5 std::unordered_multiset<int> myUnorderedMultiSet; 6 7 // 添加元素到无序多重集合 8 myUnorderedMultiSet.insert(10); 9 myUnorderedMultiSet.insert(10); // 允许重复 10 myUnorderedMultiSet.insert(20); 11 12 // 遍历无序多重集合 13 std::cout << "Unordered multiset contents: "; 14 for (int num : myUnorderedMultiSet) { 15 std::cout << num << " "; 16 } 17 std::cout << std::endl; 18 19 // 查找并计数元素 20 auto count = myUnorderedMultiSet.count(10); 21 std::cout << "Element 10 appears " << count << " times in the unordered multiset." << std::endl; 22 23 // 删除特定元素 24 myUnorderedMultiSet.erase(myUnorderedMultiSet.find(10)); // 删除一个值为10的元素 25 26 // 清空无序多重集合 27 myUnorderedMultiSet.clear(); 28 if (myUnorderedMultiSet.empty()) { 29 std::cout << "The unordered multiset is empty." << std::endl; 30 } 31 32 return 0; 33 }
10. 无序映射(std::unordered_map)
在C++中,std::unordered_map 是一种关联容器,它存储了键值对(key-value pairs),其中每个键都是唯一的。与 std::map 不同,std::unordered_map 不保证键值对的顺序,它的内部实现通常基于哈希表,这使得它在添加、删除和查找操作上都能提供平均常数时间复杂度的性能,但最坏情况下的时间复杂度可能是线性的。以下是 std::unordered_map 的一些基本特性和操作:
10.1. 特性
- 键的唯一性:每个键在
std::unordered_map中都是唯一的。 - 无序性:元素的存储顺序是不确定的,它们是无序的。
- 快速查找:基于哈希表的查找操作通常非常快。
10.2. 基本操作
- 添加元素:
insert():向映射中插入一个或多个键值对。
- 访问元素:
- 使用下标操作符
operator[]访问或修改元素(如果键不存在,会插入一个新元素)。 - 使用
at()成员函数安全地访问元素(如果键不存在,会抛出异常)。
- 删除元素:
erase():从映射中移除一个或多个指定键的元素,或者移除迭代器指定位置的元素。clear():移除映射中的所有元素。
- 查找元素:
find():查找特定键是否存在于映射中。
- 大小和空状态:
size():返回映射中元素的数量。empty():检查映射是否为空。
10.3. 示例代码
1 #include <iostream> 2 #include <unordered_map> 3 4 int main() { 5 std::unordered_map<int, std::string> myUnorderedMap; 6 7 // 添加元素到映射 8 myUnorderedMap.insert({1, "one"}); 9 myUnorderedMap[2] = "two"; // 使用下标操作符 10 myUnorderedMap[3] = "three"; 11 12 // 遍历映射 13 std::cout << "Unordered map contents: "; 14 for (const auto& pair : myUnorderedMap) { 15 std::cout << pair.first << ": " << pair.second << "; "; 16 } 17 std::cout << std::endl; 18 19 // 查找元素 20 auto it = myUnorderedMap.find(2); 21 if (it != myUnorderedMap.end()) { 22 std::cout << "Key 2 is associated with value: " << it->second << std::endl; 23 } 24 25 // 删除元素 26 myUnorderedMap.erase(it); // 删除找到的元素 27 28 // 清空映射 29 myUnorderedMap.clear(); 30 if (myUnorderedMap.empty()) { 31 std::cout << "The unordered map is empty." << std::endl; 32 } 33 34 return 0; 35 }
11. 无序多重映射(std::unordered_multimap)
在C++中,std::unordered_multimap 是一种关联容器,类似于 std::unordered_map,但它允许键(key)不是唯一的,即可以在多重映射中多次出现相同的键,每个键可以关联多个值。这使得 std::unordered_multimap 非常适合于存储一对多的关系。以下是 std::unordered_multimap 的一些基本特性和操作:
11.1. 特性
- 键的非唯一性:允许多个元素具有相同的键。
- 无序性:元素的存储顺序是不确定的,它们是无序的。
- 快速查找:基于哈希表的查找操作通常非常快。
11.2. 基本操作
- 添加元素:
insert():向多重映射中插入一个键值对。
- 访问元素:
- 使用迭代器通过
begin()和end()成员函数来访问元素。
- 删除元素:
erase():从多重映射中移除一个或多个指定键的元素,或者移除迭代器指定位置的元素。clear():移除多重映射中的所有元素。
- 查找元素:
find():查找特定键是否存在于多重映射中。count():返回多重映射中指定键的出现次数。
- 大小和空状态:
size():返回多重映射中元素的总数。empty():检查多重映射是否为空。
11.3. 示例代码
1 #include <iostream> 2 #include <unordered_map> 3 4 int main() { 5 std::unordered_multimap<int, std::string> myUnorderedMultiMap; 6 7 // 添加元素到多重映射 8 myUnorderedMultiMap.insert({1, "one"}); 9 myUnorderedMultiMap.insert({1, "uno"}); 10 myUnorderedMultiMap.insert({2, "two"}); 11 12 // 遍历多重映射 13 std::cout << "Unordered multimap contents: "; 14 for (const auto& pair : myUnorderedMultiMap) { 15 std::cout << pair.first << ": " << pair.second << "; "; 16 } 17 std::cout << std::endl; 18 19 // 查找元素 20 auto range = myUnorderedMultiMap.equal_range(1); 21 std::cout << "Values associated with key 1: "; 22 for (auto it = range.first; it != range.second; ++it) { 23 std::cout << it->second << "; "; 24 } 25 26 // 删除元素 27 myUnorderedMultiMap.erase(range.first); // 删除找到的第一个与键1关联的元素 28 29 // 清空多重映射 30 myUnorderedMultiMap.clear(); 31 if (myUnorderedMultiMap.empty()) { 32 std::cout << "The unordered multimap is empty." << std::endl; 33 } 34 35 return 0; 36 }
12. 数组(std::array)
在C++中,std::array 是标准模板库(STL)中的一个容器模板,它提供了一个固定大小的数组,其大小在编译时确定。与C++传统的数组相比,std::array 提供了更好的类型安全性和STL兼容性,同时保持了数组的紧凑性和访问效率。以下是 std::array 的一些基本特性和操作:
12.1. 特性
- 固定大小:一旦声明,其大小就不能改变。
- 类型安全:只能存储指定类型的元素。
- 连续存储:元素存储在连续的内存空间中,支持随机访问。
- 不管理内存:与自动数组(自动分配和释放)类似,
std::array不需要手动管理内存。
12.2. 基本操作
- 访问元素:
- 使用下标操作符
operator[]访问或修改元素。
- 遍历元素:
- 使用范围基
for 循环或传统 for 循环遍历元素。
- 获取大小:
size():返回数组的大小,是一个编译时常量。
- 获取最大大小:
max_size():返回数组类型可能的最大大小,实际上总是等于 size()。
- 获取元素的引用:
operator[]:提供非const和const版本,用于获取元素的引用。
- 比较:
std::equal:可以比较两个 std::array 是否相等。
12.3. 示例代码
1 #include <iostream> 2 #include <array> 3 4 int main() { 5 // 创建一个固定大小的 array,包含 5 个 int 类型的元素 6 std::array<int, 5> myArray = { 1, 2, 3, 4, 5 }; 7 8 // 访问元素 9 std::cout << "First element: " << myArray[0] << std::endl; 10 std::cout << "Last element: " << myArray.back() << std::endl; 11 12 // 修改元素 13 myArray[0] = 10; 14 15 // 遍历 array 16 for (int num : myArray) { 17 std::cout << num << " "; 18 } 19 std::cout << std::endl; 20 21 // 获取 array 的大小 22 std::cout << "Size of array: " << myArray.size() << std::endl; 23 24 return 0; 25 }
13. 元组(std::tuple)
在C++中,std::tuple 是一种包含固定数量元素的泛型容器,这些元素可以是不同的类型。std::tuple 提供了一种将不同类型的值组合在一起的方式,类似于结构体(struct),但比结构体更灵活,因为 std::tuple 的大小和类型可以在编译时确定。以下是 std::tuple 的一些基本特性和操作:
13.1. 特性
- 类型安全:可以存储不同类型的元素。
- 固定大小:一旦创建,其大小就不能改变。
- 元素访问:通过
std::get函数或下标操作符operator[]访问元素。
13.2. 基本操作
- 构造元组:
- 使用
{}和逗号分隔的初始化列表来构造std::tuple。
- 访问元素:
std::get<index>(tuple):获取指定索引位置的元素。tuple[index]:使用下标操作符访问元素(C++17起支持)。
- 遍历元组:
- 使用
std::tuple_size获取元组的大小。 - 使用
std::tie创建元组的引用。
- 比较元组:
- 使用
std::tie创建元组的引用,并使用==或!=比较两个元组。
13.3. 示例代码
1 #include <iostream> 2 #include <tuple> 3 #include <string> 4 5 int main() { 6 // 创建一个 tuple,并初始化 7 std::tuple<int, double, std::string> myTuple{ 10, 20.5, "Hello, World!" }; 8 9 // 使用 std::get 获取 tuple 中的元素 10 int myInt = std::get<0>(myTuple); // 获取第一个元素 11 double myDouble = std::get<1>(myTuple); // 获取第二个元素 12 std::string myString = std::get<2>(myTuple); // 获取第三个元素 13 14 std::cout << "Elements in tuple: " << std::endl; 15 std::cout << "Integer: " << myInt << std::endl; 16 std::cout << "Double: " << myDouble << std::endl; 17 std::cout << "String: " << myString << std::endl; 18 19 // 使用下标操作符访问 tuple 中的元素 (C++17 引入) 20 // 注意:在 C++17 之前,下标操作符不能用于 tuple 21 auto myIntBySubscript = std::get<0>(myTuple); // 等价于 myTuple[0],在 C++17 之前不可用 22 std::cout << "Integer (by subscript): " << myIntBySubscript << std::endl; 23 24 // 使用 std::tie 来创建 tuple 的引用 25 auto tie = std::tie(myInt, myDouble, myString); 26 std::cout << "Using std::tie: " << std::endl; 27 std::cout << "Integer: " << myInt << std::endl; 28 std::cout << "Double: " << myDouble << std::endl; 29 std::cout << "String: " << myString << std::endl; 30 31 // 使用 std::tuple_size 获取 tuple 的大小 32 std::cout << "Size of tuple: " << std::tuple_size<decltype(myTuple)>::value << std::endl; 33 34 // 使用 std::apply 应用函数到 tuple 上的每个元素 35 auto printElements = [](auto&&... args) { 36 (std::cout << ... << args) << std::endl; 37 }; 38 std::apply(printElements, myTuple); 39 40 return 0; 41 }
14. 栈(std::stack)
在C++中,std::stack 是一种容器适配器,它实现了后进先出(LIFO)的数据结构。这意味着最后添加到栈中的元素将是第一个被移除的元素。std::stack不直接存储元素,而是使用其他标准库容器(如 std::vector、std::deque)作为其底层容器来存储元素。以下是 std::stack 的一些基本特性和操作:
14.1. 特性
- LIFO(后进先出):元素的添加和移除仅在栈的顶部进行。
- 容器适配器:它使用另一个容器来存储元素,不分配任何额外的存储空间。
14.2. 基本操作
- 添加元素:
push():在栈顶部添加一个元素。
- 移除元素:
pop():移除栈顶部的元素。
- 访问元素:
top():访问但不移除栈顶部的元素。const_reference top() const:访问常量栈顶部的元素。
- 检查栈的状态:
empty():检查栈是否为空。size():返回栈中元素的数量。
14.3. 示例代码
1 #include <iostream> 2 #include <stack> 3 4 int main() { 5 std::stack<int> myStack; 6 7 // 添加元素到栈 8 myStack.push(1); 9 myStack.push(2); 10 myStack.push(3); 11 12 // 访问栈顶部的元素 13 while (!myStack.empty()) { 14 int topElement = myStack.top(); // 获取栈顶部的元素 15 std::cout << topElement << " "; // 打印元素 16 myStack.pop(); // 移除栈顶部的元素 17 } 18 19 std::cout << "Stack is now empty." << std::endl; 20 21 return 0; 22 }
15. 队列(std::queue)
在C++中,std::queue 是一种容器适配器,它实现了先进先出(FIFO)的数据结构。这意味着最先添加到队列中的元素将是第一个被移除的元素。std::queue 不直接存储元素,而是使用其他标准库容器(如 std::deque 或 std::list)作为其底层容器来存储元素。以下是 std::queue 的一些基本特性和操作:
15.1. 特性
- FIFO(先进先出):元素的添加和移除仅在队列的两端进行,新元素添加到末尾,移除操作从头部进行。
- 容器适配器:它使用另一个容器来存储元素,不分配任何额外的存储空间。
15.2. 基本操作
- 添加元素:
push():在队列末尾添加一个元素。
- 移除元素:
pop():移除队列头部的元素。
- 访问元素:
front():访问但不移除队列头部的元素。back():访问但不移除队列尾部的元素(C++11及以后版本支持)。
- 检查队列的状态:
empty():检查队列是否为空。size():返回队列中元素的数量。
15.3. 示例代码
1 #include <iostream> 2 #include <queue> 3 4 int main() { 5 std::queue<int> myQueue; 6 7 // 添加元素到队列 8 myQueue.push(1); 9 myQueue.push(2); 10 myQueue.push(3); 11 12 // 访问并移除队列头部的元素 13 while (!myQueue.empty()) { 14 int frontElement = myQueue.front(); // 获取队列头部的元素 15 std::cout << frontElement << " "; // 打印元素 16 myQueue.pop(); // 移除队列头部的元素 17 } 18 19 std::cout << "Queue is now empty." << std::endl; 20 21 return 0; 22 }
16. 优先队列(std::priority_queue)
在C++中,std::priority_queue 是一种容器适配器,它实现了一个优先队列数据结构。与标准队列不同,每个元素都有一个优先级,并且元素的移除顺序取决于它们的优先级,而不仅仅是它们被插入的顺序。默认情况下,std::priority_queue 是一个最大值优先队列,即默认情况下最大的元素最先被移除。以下是 std::priority_queue 的一些基本特性和操作:
16.1. 特性
- 优先级排序:元素根据优先级进行排序,而不是按照它们被插入的顺序。
- 最大值优先:默认情况下,元素按照从大到小的顺序排序。
- 只允许在一端(顶部)进行操作:新元素可以被添加到队列的末尾,而移除操作只涉及队列顶部的元素。
16.2. 基本操作
- 添加元素:
push():向优先队列末尾添加一个元素。
- 移除元素:
pop():移除优先队列顶部的元素,即当前具有最高优先级的元素。
- 访问元素:
top():访问但不移除优先队列顶部的元素。
- 检查优先队列的状态:
empty():检查优先队列是否为空。size():返回优先队列中元素的数量。
16.3. 示例代码
1 #include <iostream> 2 #include <queue> 3 4 int main() { 5 std::priority_queue<int> pq; 6 7 // 添加元素到优先队列 8 pq.push(30); 9 pq.push(10); 10 pq.push(20); 11 12 // 移除并访问队列顶部的元素 13 while (!pq.empty()) { 14 int topElement = pq.top(); // 获取优先队列顶部的元素 15 std::cout << topElement << " "; // 打印元素 16 pq.pop(); // 移除优先队列顶部的元素 17 } 18 19 std::cout << "Priority queue is now empty." << std::endl; 20 21 return 0; 22 }
时间:2024年4月30日

【C++】标准模板库STL-容器
浙公网安备 33010602011771号