别人没那么重要,我也没那么重要,好好活着,把能做的小事做好,够不到的东西就放弃,承认就好。做一个心情好能睡着的人,你所有事情都会在正轨上。

【C++】标准模板库STL-容器

  STL 容器是其中的重要组成部分,它们可以存储、组织和操作数据集合。以下是一些常用的 STL 容器:

1. 向量(std::vector

  一个动态数组,支持快速随机访问。它可以根据需要自动调整大小,适合需要频繁插入和删除的场景

  在C++中,std::vector 是标准模板库(STL)中的一个非常常用的容器,它提供了动态数组的功能。std::vector 可以存储任意类型的元素,并且可以根据需要自动调整大小以容纳更多元素。

1.1. 特性

  1. 动态数组std::vector 可以根据元素数量动态调整其存储空间。
  2. 随机访问:它提供了对元素的快速随机访问,允许通过索引直接访问元素。
  3. 类型安全:只能存储指定类型的元素。
  4. 内存管理:自动管理内存,当元素被添加或删除时,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. 特性

  1. 两端操作:可以在队列的两端快速地添加或删除元素。
  2. 动态大小std::deque 的大小可以根据元素数量动态变化。
  3. 非连续存储:与 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. 特性

  1. 双向链表:允许在链表的头部和尾部进行高效的插入和删除操作。
  2. 非连续存储:与 std::vector 不同,std::list的元素存储在非连续的内存位置。
  3. 可迭代:可以双向迭代,即从头部向尾部或从尾部向头部遍历。

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. 特性

  1. 唯一性:容器中的元素值必须是唯一的。
  2. 有序性:元素按照升序排列,每次插入的元素都会自动被放置在正确的位置以维持排序。
  3. 无序访问:不支持随机访问操作,如使用下标访问元素。

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::multisetstd::set 的一个变体,它允许容器中存在重复的元素。与 std::set一样,std::multiset 也保持其元素是有序的,通常基于平衡二叉搜索树实现。std::multiset 提供了与 std::set 类似的接口,但有一些关键的区别:

5.1. 特性

  1. 允许重复:与 std::set 不同,std::multiset 允许多个相同的元素。
  2. 有序性:元素按照升序排列,或者根据提供的比较函数排列。
  3. 无序访问:不支持随机访问操作。

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. 特性

  1. 键的唯一性:每个键在 std::map 中都是唯一的。
  2. 有序性:元素按照键的顺序自动排序。
  3. 无序访问:不支持随机访问操作,如使用下标访问元素。

6.2. 基本操作

  • 添加元素
    • insert():向映射中插入一个或多个键值对。
  • 访问元素
    • 使用下标操作符 operator[] 访问或修改元素(会插入键,如果键不存在)。
    • 使用 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::multimapstd::map 的一个变体,它允许键(key)不是唯一的,即可以在映射中多次出现相同的键,每个键可以关联多个值。这与 std::map 形成对比,后者要求每个键都是唯一的。std::multimap 通常也是基于平衡二叉搜索树实现的,它保持了元素按照键的顺序自动排序。以下是 std::multimap 的一些基本特性和操作:

7.1. 特性

  1. 键的非唯一性:允许多个元素具有相同的键。
  2. 有序性:元素按照键的顺序自动排序。
  3. 无序访问:不支持随机访问操作

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. 特性

  1. 唯一性:容器中的元素值必须是唯一的。
  2. 无序性:元素的存储顺序是不确定的,它们是无序的。
  3. 快速查找:基于哈希表的查找操作通常非常快。

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. 特性

  1. 允许重复:可以存储相同元素的多个副本。
  2. 无序性:元素的存储顺序是不确定的,它们是无序的。
  3. 快速查找:基于哈希表的查找操作通常非常快。

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. 特性

  1. 键的唯一性:每个键在 std::unordered_map 中都是唯一的。
  2. 无序性:元素的存储顺序是不确定的,它们是无序的。
  3. 快速查找:基于哈希表的查找操作通常非常快。

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. 特性

  1. 键的非唯一性:允许多个元素具有相同的键。
  2. 无序性:元素的存储顺序是不确定的,它们是无序的。
  3. 快速查找:基于哈希表的查找操作通常非常快。

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. 特性

  1. 固定大小:一旦声明,其大小就不能改变。
  2. 类型安全:只能存储指定类型的元素。
  3. 连续存储:元素存储在连续的内存空间中,支持随机访问。
  4. 不管理内存:与自动数组(自动分配和释放)类似,std::array 不需要手动管理内存。

12.2. 基本操作

  • 访问元素
    • 使用下标操作符 operator[]访问或修改元素。
  • 遍历元素
    • 使用范围基 for 循环传统 for 循环遍历元素。
  • 获取大小
    • size():返回数组的大小,是一个编译时常量。
  • 获取最大大小
    • max_size():返回数组类型可能的最大大小,实际上总是等于 size()
  • 获取元素的引用
    • operator[]:提供 非constconst 版本,用于获取元素的引用。
  • 比较
    • 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. 特性

  1. 类型安全:可以存储不同类型的元素。
  2. 固定大小:一旦创建,其大小就不能改变。
  3. 元素访问:通过 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::vectorstd::deque)作为其底层容器来存储元素。以下是 std::stack 的一些基本特性和操作:

14.1. 特性

  1. LIFO(后进先出):元素的添加和移除仅在栈的顶部进行。
  2. 容器适配器:它使用另一个容器来存储元素,不分配任何额外的存储空间。

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::dequestd::list)作为其底层容器来存储元素。以下是 std::queue 的一些基本特性和操作:

15.1. 特性

  1. FIFO(先进先出):元素的添加和移除仅在队列的两端进行,新元素添加到末尾,移除操作从头部进行。
  2. 容器适配器:它使用另一个容器来存储元素,不分配任何额外的存储空间。

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. 特性

  1. 优先级排序:元素根据优先级进行排序,而不是按照它们被插入的顺序。
  2. 最大值优先:默认情况下,元素按照从大到小的顺序排序。
  3. 只允许在一端(顶部)进行操作:新元素可以被添加到队列的末尾,而移除操作只涉及队列顶部的元素。

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日

posted @ 2024-04-30 10:17  一路狂奔的乌龟  阅读(100)  评论(0)    收藏  举报
返回顶部