揭秘Map与Set的键值奥秘与集合魅力,解锁高效数据魔法

在这里插入图片描述

文章目录

  • 前言
    • ➰一、关联式容器
      • 1.1 关联式容器的概述
      • 1.2 关联式容器的工作原理
      • 1.3 关联式容器的核心特性
    • ➰二、键值对
      • 2.1 键值对的基本概念
      • 2.2 键值对在C++中的实现
    • ➰三、树形结构的关联式容器
      • 3.1 树形结构的特点
      • 3.2 使用场景
    • ➰四、set的使用与定义
      • 4.1 set的基本特性
      • 4.2 set的声明与构造
      • 4.3 set的成员函数
      • 4.4 set的迭代器
      • 4.5 set的使用示例
    • ➰五、multiset的定义与使用
      • 5.1 multiset基本特性
      • 5.2 multiset的声明与构造
      • 5.3 multiset的成员函数
      • 5.4 multiset的自定义排序
      • 5.5 multiset的使用示例
    • ➰六、map的定义与使用
      • 6.1 map的定义
      • 6.2 map的插入元素
      • 6.3 map的查找元素
      • 6.4 map的遍历元素
      • 6.5 map的删除元素
      • 6.6 map的其他成员函数
      • 6.7 map的自定义排序
      • 6.8 map的的使用样例
    • ➰七、multimap的定义与使用
      • 7.1 multimap的定义
      • 7.2 multimap插入元素
      • 7.3 multimap查找元素
      • 7.4 multimap遍历元素
      • 7.5 multimap删除元素
      • 7.6 multimap的其他成员函数
      • 7.7 注意事项
  • 结语


前言

在C++编程的浩瀚宇宙中,标准模板库(STL)犹如一颗璀璨的星辰,为开发者们提供了强大的数据结构和算法支持。而在STL的众多容器中,Map与Set无疑是两颗尤为耀眼的明珠,它们以高效、有序的方式管理着数据,让键值对和集合的处理变得轻松自如。
本文将带你一起深入探索C++ STL中的Map与Set容器,揭开它们高效数据管理的神秘面纱。从基本用法到底层实现原理,再到实际应用中的


➰一、关联式容器

在C++的编程世界中,关联式容器是数据结构领域中的瑰宝,它们不仅提供了高效的数据存储和检索功能,还通过键值对的映射机制,极大地丰富了程序设计的灵活性和多样性。本文将深入探讨C++关联式容器的核心特性、工作原理以及创新应用,为您揭开这些强大工具的神秘面纱。

1.1 关联式容器的概述

C++标准库中的关联式容器主要包括std::mapstd::setstd::multimapstd::multiset等。它们共同的特点是基于键值对(key-value)或纯键(key-only)进行存储和检索,支持高效的查找、插入和删除操作。

  • std::map:基于红黑树实现的有序关联数组,支持高效的键值对查找、插入和删除。
  • std::set:基于红黑树实现的有序集合,只存储唯一的键,支持高效的查找、插入和删除。
  • std::multimap:与std::map类似,但允许键的重复。
  • std::multiset:与std::set类似,但允许键的重复。

1.2 关联式容器的工作原理

关联式容器内部通常使用平衡二叉树(如红黑树)来实现高效的查找、插入和删除操作。这些操作的时间复杂度通常为O(log n),其中n是容器中元素的数量。平衡二叉树通过自动调整树的结构来保持平衡,从而确保操作的高效性。

1.3 关联式容器的核心特性

  1. 有序性:关联式容器中的元素按照键的顺序进行存储,这使得它们非常适合用于需要排序的场景。
  2. 唯一性std::mapstd::set中的键是唯一的,这确保了数据的唯一性和一致性。
  3. 键值对映射std::mapstd::multimap通过键值对的方式存储数据,这使得它们能够轻松地实现数据的映射和查找。
  4. 范围查询:关联式容器支持基于键的范围查询,可以方便地查找某个范围内的所有元素。

➰二、键值对

在C++中,键值对(Key-Value Pair)是一种常见的数据结构,它由一个键(Key)和一个值(Value)组成。这种结构在编程中非常有用,因为它允许你通过键来快速查找、更新或删除与之关联的值。

2.1 键值对的基本概念

  • 键(Key):键是唯一的标识符,用于访问与之关联的值。在C++中,键通常是某种数据类型(如整数、字符串等)的实例。
  • 值(Value):值是存储在键值对中的实际数据。值可以是任何数据类型,包括基本数据类型(如整数、浮点数、字符等)和复杂数据类型(如对象、结构体等)。

2.2 键值对在C++中的实现

在C++中,键值对通常通过以下几种方式实现:

  1. std::mapstd::unordered_map
    • std::map 是一个关联容器,它存储键值对,并根据键的排序顺序自动排序这些对。默认情况下,std::map 使用 < 运算符来比较键。
    • std::unordered_map 是另一个关联容器,它也存储键值对,但不保证元素的顺序。它使用哈希表来实现快速查找、插入和删除操作。
  2. std::pair
    • std::pair 是一个模板类,它创建了一个包含两个数据成员的对象。这两个数据成员分别被称为 firstsecond,可以分别用作键和值。虽然 std::pair 本身不直接实现键值对的存储和查找功能,但它经常与 std::mapstd::unordered_map 或其他容器一起使用来存储键值对。
  3. 自定义数据结构:
    • 在某些情况下,你可能需要创建自己的数据结构来存储键值对。这通常涉及到定义一个类,该类包含两个成员变量(一个用于键,一个用于值),以及必要的成员函数来访问和修改这些成员。

➰三、树形结构的关联式容器

3.1 树形结构的特点

这些树形结构的关联式容器具有以下特点:

  • 有序性:元素根据键的排序顺序进行存储,因此可以像数组一样进行顺序遍历。
  • 平衡性:使用平衡二叉树(如红黑树)来维护元素,从而保证了查找、插入和删除操作的时间复杂度为O(log n)。
  • 自动排序:在插入新元素时,容器会自动将其插入到正确的位置,以保持元素的排序顺序。
  • 键的唯一性(对于std::mapstd::set:这些容器保证键的唯一性,即不允许插入具有相同键的多个元素(对于std::multimapstd::multiset则允许键的重复)。

3.2 使用场景

树形结构的关联式容器在C++中有广泛的应用场景,包括但不限于:

  • 字典和映射std::mapstd::multimap可以用于实现字典和映射,其中键是单词或标识符,值是相应的定义或数据。
  • 集合操作std::setstd::multiset可以用于实现集合操作,如并集、交集和差集等。
  • 排序和去重:这些容器可以用于对元素进行排序和去重操作。
  • 查找和替换:由于这些容器提供了快速的查找操作,因此它们可以用于实现查找和替换功能。

总之,树形结构的关联式容器是C++标准库中非常强大且灵活的数据结构,它们提供了高效的查找、插入和删除操作,并且保证了元素的排序顺序和键的唯一性(对于std::mapstd::set)。

➰四、set的使用与定义

4.1 set的基本特性

  • 存储不重复元素:set中的每个元素都是唯一的,不允许有重复值。
  • 自动排序:set中的元素会按照一定的顺序排列,可以是自然顺序或者根据自定义的比较函数进行排序。
  • 元素不可修改:set中的元素值不能直接被改变,因为元素值就是其键值,关系到set元素的排列规则。
  • 高效操作:set支持快速的查找、插入和删除操作,时间复杂度通常为O(log n),这是由于其底层实现采用红黑树这种平衡二叉搜索树结构。

4.2 set的声明与构造

  • 声明set<typename> name;,其中typename可以是任何基本类型(如int、double、char等),也可以是STL标准容器(如vector、set、queue等)。
  • 构造
    • 默认构造函数:set<typename> name;,创建一个空的set。
    • 拷贝构造函数:set<typename> name(const set<typename>& other);,创建一个新的set,它是现有set的副本。
    • 初始化列表构造:set<typename> name{val1, val2, ...};,使用初始化列表来构造set。
    • 范围构造:set<typename> name(first, last);,使用一个迭代器范围[first, last)来构造set。

4.3 set的成员函数

  • 插入元素
    • insert(const typename& value);:将一个元素插入到set中。如果元素已存在,则插入操作将被忽略。
    • pair<iterator, bool> insert(const typename& value);:返回一个pair,其中iterator指向插入的位置,bool表示插入是否成功。
  • 删除元素
    • erase(iterator pos);:删除迭代器pos指向的元素。
    • erase(const typename& value);:删除值为value的元素。
    • erase(iterator first, iterator last);:删除范围[first, last)内的所有元素。
  • 查找元素
    • find(const typename& value);:查找值为value的元素,返回一个指向该元素的迭代器。如果未找到,则返回end()。
    • count(const typename& value);:返回值为value的元素在set中出现的次数。对于set来说,返回值只能是0或1。
  • 其他成员函数
    • size();:返回set中元素的个数。
    • empty();:判断set是否为空。如果为空,返回true;否则返回false。
    • clear();:清空set中的所有元素。
    • begin();:返回一个指向set中第一个元素的迭代器。
    • end();:返回一个指向set末尾的迭代器(注意,这是一个“尾后迭代器”,不指向任何实际元素)。
    • lower_bound(const typename& value);:返回指向第一个不小于value的元素的迭代器。
    • upper_bound(const typename& value);:返回指向第一个大于value的元素的迭代器。
    • equal_range(const typename& value);:返回一个pair,表示value在set中的范围(即[lower_bound, upper_bound))。

4.4 set的迭代器

set的迭代器是双向迭代器,支持正向和反向遍历。由于set中的元素是有序的,所以迭代器的遍历顺序也是有序的。此外,set的迭代器是const_iterator,这意味着不能通过迭代器直接修改元素的值。

4.5 set的使用示例

以下是一个简单的使用示例,展示了如何创建set、插入元素、查找元素和遍历元素:

#include <iostream>  
#include <set>  using namespace std;  // set的基本使用
void test_set1() {// 排序+去重set<int> s;s.insert(2);s.insert(4);s.insert(5);s.insert(1);s.insert(7);s.insert(7); // 去重原理:一个值已经有了,我们就不插入auto it = s.begin();while (it != s.end()) {cout << *it << " ";++it;}cout << endl;for (auto e : s) {cout << e << " ";}cout << endl;/*auto pos = s.find(3);if(pos != s.end())s.erase(pos);*/s.erase(1);for (auto e : s) {cout << e << " ";}cout << endl;
}// set迭代器的使用
void test_set2() {set<int> myset;set<int>::iterator itlow, itup;for (int i = 1; i < 10; i++)myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90// 删除[30 60],但是迭代器是左闭右开itlow = myset.lower_bound(30);                // 下限 >=     itup = myset.upper_bound(60);                 // 上限 >// [itlow, itup)cout << *itlow << endl;cout << *itup << endl;myset.erase(itlow, itup);for (auto e : myset) {cout << e << " ";}cout << endl;
}int main(){test_set1();cout << endl << endl;test_set2();return 0;
}

综上所述,C++中的set是一种非常实用的容器,它提供了高效的查找、插入和删除操作,并且保证了元素的唯一性和有序性。

➰五、multiset的定义与使用

在C++中,multiset是一种非常有用的标准模板库(STL)容器,它用于存储一组按照特定顺序排列的元素,并且允许元素重复。以下是对multiset的详细介绍:

5.1 multiset基本特性

  1. 存储重复元素:与set容器不同,multiset允许存储重复的元素。
  2. 自动排序multiset中的元素会根据一定的顺序(默认是升序)自动进行排序。
  3. 元素不可直接修改multiset中的元素值在插入后不能直接被修改,因为元素值就是其键值,直接修改会破坏容器的有序性。不过,可以通过删除旧元素并插入新元素的方式来间接修改。
  4. 底层实现multiset的底层通常使用红黑树这种平衡二叉搜索树结构来实现,以确保高效的查找、插入和删除操作。

5.2 multiset的声明与构造

  1. 声明multiset<typename> name;,其中typename表示要存储的元素类型。
  2. 构造:
    • 默认构造函数:multiset<typename> name;,创建一个空的multiset
    • 拷贝构造函数:multiset<typename> name(const multiset<typename>& other);,创建一个新的multiset,它是现有multiset的副本。
    • 初始化列表构造:multiset<typename> name{val1, val2, ...};,使用初始化列表来构造multiset
    • 范围构造:multiset<typename> name(first, last);,使用一个迭代器范围[first, last)来构造multiset

5.3 multiset的成员函数

multiset提供了丰富的成员函数来操作容器中的元素,包括但不限于:

  1. 插入元素:
    • insert(const typename& value);:将一个元素插入到multiset中。如果元素已存在,则会在保持有序性的前提下,将新元素插入到已有元素的后面(因为允许重复)。
    • iterator insert(const_iterator position, const typename& value);:在指定位置position前插入一个元素,并返回指向新插入元素的迭代器。如果position是end()迭代器,则元素会被添加到容器的末尾。
    • 还有其他形式的insert函数,如使用范围插入、使用初始化列表插入等。
  2. 删除元素
    • erase(iterator pos);:删除迭代器pos指向的元素。
    • erase(const typename& value);:删除值为value的所有元素。
    • erase(iterator first, iterator last);:删除范围[first, last)内的所有元素。
  3. 查找元素
    • find(const typename& value);:查找值为value的元素,返回一个指向该元素的迭代器。如果未找到,则返回end()迭代器。
    • count(const typename& value);:返回值为value的元素在multiset中出现的次数。
  4. 其他成员函数
    • size();:返回multiset中元素的个数。
    • empty();:判断multiset是否为空。如果为空,返回true;否则返回false。
    • clear();:清空multiset中的所有元素。
    • begin();end();:分别返回一个指向multiset中第一个元素和末尾元素的迭代器(尾后迭代器)。
    • rbegin();rend();:分别返回一个指向multiset中最后一个元素和第一个元素前面的位置的逆向迭代器。
    • lower_bound(const typename& value);:返回指向第一个不小于value的元素的迭代器。
    • upper_bound(const typename& value);:返回指向第一个大于value的元素的迭代器。
    • equal_range(const typename& value);:返回一个pair,表示valuemultiset中的范围(即[lower_bound, upper_bound))。

5.4 multiset的自定义排序

默认情况下,multiset中的元素会按照其类型的默认比较函数(通常是<运算符)进行排序。如果需要自定义排序规则,可以在声明multiset时提供一个自定义的比较函数或比较类。例如:

struct Compare {  bool operator()(const int& a, const int& b) const {  return a > b; // 降序排序  }  
};  multiset<int, Compare> myMultiset;

在这个例子中,我们定义了一个比较类Compare,它重载了operator()来指定降序排序规则。然后,我们使用这个比较类来创建一个multiset对象myMultiset,它将按照降序对元素进行排序。

5.5 multiset的使用示例

以下是一个简单的使用示例,展示了如何创建multiset、插入元素、查找元素和遍历元素:

#include <iostream>  
#include <set>  using namespace std;  int main() {  multiset<int> myset;multiset<int>::iterator itlow, itup;// 插入元素,允许重复myset.insert(1);myset.insert(3);myset.insert(1);myset.insert(4);myset.insert(1);myset.insert(1);for (auto e : myset) {cout << e << " ";}cout << endl;// count返回1的个数cout << myset.count(1) << endl;// 返回一个pair,表示value在multiset中的范围(即[lower_bound, upper_bound))。auto ret = myset.equal_range(1);itlow = ret.first;itup = ret.second;// 删除区间内的所有1myset.erase(itlow, itup);for (auto e : myset) {cout << e << " ";}cout << endl;return 0;  
}

➰六、map的定义与使用

在C++中,map是一种非常有用的标准模板库(STL)容器,它用于存储键值对(key-value pairs),其中每个键都是唯一的,并且与一个特定的值相关联。以下是map的使用与定义的详细介绍:

6.1 map的定义

map的定义通常使用以下语法:

map<KeyType, ValueType> mapName;

其中,KeyType表示键的类型,ValueType表示值的类型,mapNamemap对象的名称。

例如,定义一个存储字符串到整数的映射的map

map<string, int> myMap;

6.2 map的插入元素

map中插入元素有多种方法:

  1. 使用insert成员函数:
myMap.insert(pair<string, int>("key1", 100));

或者:

myMap.insert(make_pair("key2", 200));
  1. 使用下标运算符[]直接赋值(如果键不存在,则插入新键值对;如果键已存在,则更新对应的值):
myMap["key3"] = 300;

举例:

void test_map1() {map<string, string> dict;// 1.有名对象pair<string, string> kv1("insert", "插入");dict.insert(kv1);// 2.匿名对象dict.insert(pair<string, string>("sort", "排序"));// 3.make_pairdict.insert(make_pair("string", "字符串"));// 4.C++11 多参数的构造函数的隐式类型转换:构造+拷贝构造优化成一步dict.insert({ "list", "双向链表" });auto it = dict.begin();while (it != dict.end()) {cout << it->first << ":" << it->second << " ";++it;}cout << endl;
}

6.3 map的查找元素

可以使用find成员函数来查找元素:

auto it = myMap.find("key1");  
if (it != myMap.end()) {  cout << "Found: " << it->first << " => " << it->second << endl;  
} else {  cout << "Key not found." << endl;  
}

find函数返回一个迭代器,如果找到了指定的键,则迭代器指向该元素;否则,迭代器等于end()

6.4 map的遍历元素

可以使用迭代器来遍历map中的所有元素:

for (auto it = myMap.begin(); it != myMap.end(); ++it) {  cout << it->first << " => " << it->second << endl;  
}

或者使用范围for循环(C++11及以上):

for (const auto& pair : myMap) {  cout << pair.first << " => " << pair.second << endl;  
}

6.5 map的删除元素

可以使用erase成员函数来删除元素:

  1. 通过键删除:
myMap.erase("key1");
  1. 通过迭代器删除:
auto it = myMap.find("key2");  
if (it != myMap.end()) {  myMap.erase(it);  
}
  1. 删除一个范围内的元素(通过两个迭代器):
auto it_begin = myMap.find("key_start");  
auto it_end = myMap.find("key_end");  
if (it_begin != myMap.end() && ++(it_end.first) != myMap.end()) {  myMap.erase(it_begin, it_end);  
}

注意:在删除范围内的元素时,需要确保迭代器是有效的,并且it_end应该指向要删除范围之外的第一个元素的位置(因此需要对it_end的迭代器进行自增操作,但这里需要注意it_end可能是end()迭代器,此时不能自增)。然而,上面的代码示例在逻辑上是有问题的,因为find返回的是单个元素的迭代器,而不是一个可以表示范围的迭代器对。正确的做法应该是使用其他方式来确定要删除的范围,比如使用lower_boundupper_bound函数。

6.6 map的其他成员函数

map还提供了其他有用的成员函数,如:

  • size():返回map中元素的个数。
  • empty():判断map是否为空。
  • clear():清空map中的所有元素。
  • count(const Key& key):返回键为key的元素个数(对于map来说,返回值只能是0或1,因为键是唯一的)。
  • lower_bound(const Key& key)upper_bound(const Key& key):分别返回指向第一个不小于(大于)key的元素的迭代器。
  • equal_range(const Key& key):返回一个pair,表示keymap中的范围(即[lower_bound, upper_bound))。

6.7 map的自定义排序

默认情况下,map中的元素会按照键的升序进行排序。如果需要自定义排序规则,可以在声明map时提供一个自定义的比较函数或比较类。例如:

struct Compare {  bool operator()(const int& a, const int& b) const {  return a > b; // 降序排序  }  
};  map<int, string, Compare> myMap;

在这个例子中,我们定义了一个比较类Compare,它重载了operator()来指定降序排序规则。然后,我们使用这个比较类来创建一个map对象myMap,它将按照降序对键进行排序。

6.8 map的的使用样例

#include <iostream>
using namespace std;void test_map2() {map<string, string> dict;dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("insert", "插入"));// 不插入,不覆盖,只看key,右值value不相同无所谓dict.insert(make_pair("insert", "xxxxx"));auto it = dict.begin();while (it != dict.end()) {// cout << (*it).first << ":" << (*it).second;cout << it->first << ":" << it->second << " ";++it;}cout << endl;for (const auto& kv : dict) {cout << kv.first << ":" << kv.second << " ";}
}// map.operator[],通过key,返回value
void test_map3() {// 统计次数string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countmap;for (auto e : arr) {/*auto it = countmap.find(e);if (it == countmap.end()) {countmap.insert(make_pair(e, 1));}else {it->second++;}*/// value_type& operator[](const key_type k)countmap[e]++;}for (const auto& kv : countmap){cout << kv.first << ":" << kv.second << endl;}
}void test_map4()
{map<string, string> dict;dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("insert", "插入"));cout << dict["sort"] << endl; // 查找和读dict["map"];                  // 插入dict["map"] = "映射,地图";     // 修改dict["insert"] = "xxx";       // 修改dict["set"] = "集合";         // 插入+修改for (const auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}
}int main() {test_map2();cout << endl << endl;cout << endl << endl;test_map3();cout << endl << endl;cout << endl << endl;test_map4();cout << endl << endl;cout << endl << endl;return 0;
}

综上所述,map在C++中是一个功能强大的容器,它提供了方便的键值对存储和查找功能,并且支持自定义排序规则。

➰七、multimap的定义与使用

在C++中,multimap是一个关联容器,它与map相似,但允许键值对中的键可以重复。以下是对multimap的定义与使用的详细介绍:

7.1 multimap的定义

multimap的定义通常使用以下语法:

multimap<KeyType, ValueType> multimapName;

其中,KeyType表示键的类型,ValueType表示值的类型,multimapNamemultimap对象的名称。

例如,定义一个存储字符串到整数的映射的multimap

multimap<string, int> myMultimap;

7.2 multimap插入元素

multimap中插入元素有多种方法,通常使用insert成员函数:

myMultimap.insert(pair<string, int>("key1", 100));

或者:

myMultimap.insert(make_pair("key2", 200));

由于multimap允许键重复,因此可以插入多个具有相同键的元素。

7.3 multimap查找元素

查找元素时,可以使用find成员函数,但需要注意的是,find函数只返回第一个找到的具有指定键的元素。如果需要查找所有具有相同键的元素,可以使用equal_rangelower_boundupper_bound成员函数。

  • find成员函数:
auto it = myMultimap.find("key1");  
if (it != myMultimap.end()) {  cout << "Found: " << it->first << " => " << it->second << endl;  
} else {  cout << "Key not found." << endl;  
}
  • equal_range成员函数:返回一个pair,其中first成员是指向第一个不小于给定键的元素的迭代器,second成员是指向第一个大于给定键的元素的迭代器。这可以用于查找所有具有相同键的元素。
auto range = myMultimap.equal_range("key1");  
for (auto it = range.first; it != range.second; ++it) {  cout << it->first << " => " << it->second << endl;  
}
  • lower_boundupper_bound成员函数:分别返回指向第一个不小于(大于)给定键的元素的迭代器。
auto lb = myMultimap.lower_bound("key1");  
auto ub = myMultimap.upper_bound("key1");  
for (auto it = lb; it != ub; ++it) {  cout << it->first << " => " << it->second << endl;  
}

7.4 multimap遍历元素

可以使用迭代器来遍历multimap中的所有元素:

for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) {  cout << it->first << " => " << it->second << endl;  
}

或者使用范围for循环(C++11及以上):

for (const auto& pair : myMultimap) {  cout << pair.first << " => " << pair.second << endl;  
}

7.5 multimap删除元素

可以使用erase成员函数来删除元素:

  1. 通过键删除(删除所有具有指定键的元素):
myMultimap.erase("key1");
  1. 通过迭代器删除:
auto it = myMultimap.find("key2");  
if (it != myMultimap.end()) {  myMultimap.erase(it); // 注意:这将只删除找到的第一个元素,如果有多个相同键的元素,需要额外处理  
}

注意:上面的代码只会删除找到的第一个具有指定键的元素。如果需要删除所有具有相同键的元素,应该使用equal_rangelower_boundupper_bound来找到所有相关元素,并逐个删除。

  1. 删除一个范围内的元素(通过两个迭代器):
auto it_begin = myMultimap.lower_bound("key_start");  
auto it_end = myMultimap.upper_bound("key_end");  
myMultimap.erase(it_begin, it_end);

7.6 multimap的其他成员函数

multimap还提供了其他有用的成员函数,如:

  • size():返回multimap中元素的个数。
  • empty():判断multimap是否为空。
  • clear():清空multimap中的所有元素。
  • count(const Key& key):返回键为key的元素个数(对于multimap来说,这个值可能大于1)。

7.7 注意事项

  • multimap中的元素是按照键的顺序存储的,默认情况下是按照键的升序进行排序。如果需要自定义排序规则,可以在声明multimap时提供一个自定义的比较函数或比较类。
  • 由于multimap允许键重复,因此在插入、查找和删除元素时需要特别注意处理多个相同键的情况。

综上所述,multimap在C++中是一个功能强大的容器,它提供了方便的键值对存储和查找功能,并且支持自定义排序规则和处理多个相同键的情况。


结语

最后,需要强调的是,虽然Map与Set提供了高效的数据管理方式,但在使用时仍需注意其性能特点和适用场景。只有深入了解并合理利用这些容器的特性,我们才能在程序中充分发挥它们的作用,实现更加高效、稳定的数据管理。希望本文能够为你提供有益的参考和帮助,让你在C++编程的道路上更加游刃有余。
在这里插入图片描述

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,17的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是17前进的动力!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/452359.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter UI组件库(JUI)

Flutter UI组件库 (JUI) 介绍 您是否正在寻找一种方法来简化Flutter开发过程&#xff0c;并创建美观、一致的用户界面&#xff1f;您的搜索到此为止&#xff01;我们的Flutter UI组件库&#xff08;JUI&#xff09;提供了广泛的预构建、可自定义组件&#xff0c;帮助您快速构建…

RHCE--ntp客户端,时间服务器服务端

NTP 是网络时间协议&#xff08; Network Time Protocol &#xff09;的简称&#xff0c;通过 udp 123 端口进行网络时钟同步。 Chrony 是一个开源自由的网络时间协议 NTP 的客户端和服务器软件。它能让计算机保持系统时钟与时钟服务器&#xff08; NTP &#xff09;同步&#…

计算机网络:数据链路层 —— 以太网(Ethernet)

文章目录 局域网局域网的主要特征 以太网以太网的发展100BASE-T 以太网物理层标准 吉比特以太网载波延伸物理层标准 10吉比特以太网汇聚层交换机物理层标准 40/100吉比特以太网传输媒体 局域网 局域网&#xff08;Local Area Network, LAN&#xff09;是一种计算机网络&#x…

基于SSM果蔬经营系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商品信息管理&#xff0c;类型管理&#xff0c;系统管理&#xff0c;订单管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;商品信息&#xff0c;广告…

爬虫+数据保存

爬虫以及数据保存 这篇文章, 分享如何将爬虫爬到的数据, 保存到excel表格当中。 文章目录 1.安装保存数据的第三方库openpyxl并使用 2.爬虫加单表数据保存 3.爬虫加多表数据保存 4.实战 一、安装保存数据的第三方库openpyxl并使用 我们需要安装openpyxl的第三方库 安装…

Qt第十三天:网络编程:TCP和UDP的使用

我发现了有些人喜欢静静看博客不聊天呐&#xff0c; 但是ta会点赞。 这样的人呢帅气低调有内涵&#xff0c; 美丽大方很优雅。 说的就是你&#xff0c; 不用再怀疑哦 ❤️TCP&#xff1a; 一、创建项目&#xff0c;命名为Server&#xff0c;继承QWidget 二、添加Qt设计师…

CentOS7安装RabbitMQ-3.13.7、修改端口号

本文安装版本&#xff1a; Erlang&#xff1a;26.0 官网下载地址 Erlang RabbitMQ&#xff1a;3.13.7 官网下载地址 RabbitMQ RabbitMQ和Erlang对应关系查看&#xff1a;https://www.rabbitmq.com/which-erlang.html 注&#xff1a;安装erlang之前先安装下依赖文件&#xff0…

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统&#xff0c;功能带有卡密生成和添加黑名单等&#xff0c;源码放在我的网盘里已经两年之久&#xff0c;由于玖逸现在已经跑路了所以现在发出来分享给大家&#xff0c;需要的可以自己拿去而开&#xff0c;反正功能也不是很多具体的自己…

Teledyne LeCroy:800G高速以太网一站式自动化测试解决方案(网络打流测试+物理层加压干扰+协议分析)

LinkExpert一站式测试解决方案 LinkExpert 是一款软件应用程序&#xff0c;可对Teledyne LeCroy的协议分析仪和训练器进行自动化硬件控制和管理。除了作为合规性、一致性和验证测试的便捷接口外&#xff0c;它还能轻松地将这些测试添加到自动回归测试流程中。 现在&#xff0c;…

WPF基础权限系统

一.开发环境 VisualStudio 2022NET SDK 8.0Prism 版本 8.1.97Sqlite 二. 功能介绍 WPF 基础权限系统&#xff0c;是一个支持前后端分离设计的 客户端(C/S)项目&#xff0c;该示例项目前端xaml使用UI库 &#xff0c;Material Design Themes UI 来构建用户界面&#xff0c;确保…

C# -- Abstract、Virtual、interface

一、Virtual方法&#xff08;虚方法&#xff09; 1&#xff09;virtual 关键字用于在基类&#xff08;父类&#xff09;中修饰方法 2&#xff09;基类中定义了virtual方法&#xff0c;派生类中使用override重写该方法 二、Abstract方法&#xff08;抽象方法&#xff09; 1&…

【ssh】Mac 使用 ssh 连接阿里云报错:Connection reset by 8.155.1.xxx port 22

Mac 使用 ssh 连接阿里云报错&#xff1a;Connection reset by 8.155.1.xxx port 22 问题描述解决办法 问题描述 Connection reset by 8.155.1.xxx port 22解决办法 关掉代理 VPN

CTFHUB技能树之XSS——存储型

开启靶场&#xff0c;打开链接&#xff1a; 发现地址栏中的URL没有GET传参&#xff0c;而且这次是“Hello&#xff0c;no name” 还是跟反射型一样的流程&#xff1a; 先注入一下看看&#xff1a; <script>alert(1)</script> 但界面的结果还是“Hello&#xff0c…

【网络协议】之 HTTP 协议详解

HTTP 协议是 Web 的基石&#xff0c;它定义了客户端和服务器之间的通信规则。本文将深入地探讨 HTTP 的核心概念&#xff0c;包括工作原理、请求方法、状态码以及不同 HTTP 版本的演进。 一、HTTP 的工作原理 HTTP 协议基于客户端-服务器模型&#xff0c;遵循请求-响应的循环&…

FineReport 计算同比增长

1、数据库查询 SELECTt1.年,t1.月,t1.总金额 AS 同期金额,t1.仓库名称,t2.总金额 AS 上期金额 FROMtest t1LEFT JOIN test t2 ON ( t1.年 t2.年 1 ) AND t1.月 t2.月 AND t1.仓库名称 t2.仓库名称2、配置字段 月份字段加后缀 月 数据列加后缀 计算同比增长率 if(LEN(B3)0 …

2024年五一杯数学建模C题煤矿深部开采冲击地压危险预测求解全过程论文及程序

2024年五一杯数学建模 C题 煤矿深部开采冲击地压危险预测 原题再现&#xff1a; “煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开采。在…

VScode背景更改

效果 实现方法 第0步 以管理员身份运行VScode 首先 需要安装这个扩展 然后 接下来 找到配置文件 再后来 在配置文件的下面但不超过最后一个大括号的地方加入以下内容 "update.enableWindowsBackgroundUpdates": true,"background.fullscreen": {…

Nature 正刊丨群体爆发中的神经元序列在人类皮层中编码信息

01摘要 传统上&#xff0c;神经编码是通过对不同刺激的放电率和潜伏期的变化来检查的1,2,3,4,5。然而&#xff0c;神经元群体也可能表现出短暂的尖峰活动爆发&#xff0c;其中神经元以特定的时间顺序或序列放电6,7,8。人脑可以利用群体爆发中的这些神经元序列来有效地表示信息…

React中的useState和useEffect解析

一、组件状态管理——useState 1.定义 useState 是一个 React Hook&#xff08;函数&#xff09;&#xff0c;它允许我们向组件添加一个状态变量&#xff0c;从而控制影响组件的渲染结果 和普通JS变量不同的是&#xff0c;状态变量一旦发生变化组件的视图UI也会跟着变化&…

力扣 中等 82.删除排序链表中的重复元素 II

文章目录 题目介绍题解 题目介绍 题解 只需在83题基础上加一个while循环即可 class Solution {public ListNode deleteDuplicates(ListNode head) {ListNode dummy new ListNode(101, head);ListNode cur dummy;while (cur.next ! null && cur.next.next ! null) {…