当前位置:   article > 正文

C++编程语言STL之map介绍_map stl

map stl

本文主要介绍C++编程语言的STL(Standard Template Library)中map容器及相关容器的相关知识,同时通过示例代码介绍这些容器的常见用法。

1 概述

关联容器(associative-container)和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。

虽然关联容器的很多行为与顺序容器相同,但其不同之处反映了关键字的作用。关联容器支持高效的关键字查找和访问。

两个主要的关联容器类型为mapset。map中的元素是一些“关键字-值对(key-value)”:“关键字”起索引的作用,“值”则表示与索引相关联的数据。set中每个元素只包含一个关键字。

2 map

2.1 特性

map的特性如下:

  • 每个关键字只能出现一次;
  • 默认按key的升序存储元素;
  • 使用红黑树(red-black trees)作为底层数据结构。

2.2 常见用法

2.2.1 构造map

构造map的方法如下(以键值对为“int-string”类型为例):

map<int, string> mapStudent;

2.2.2 插入元素

map提供了几种插入元素的方法。

使用insert函数插入pair数据:

  1. mapStudent.insert(pair<int, string>(1, "zhao"));
  2. mapStudent.insert(pair<int, string>(2, "qian"));
  3. mapStudent.insert(pair<int, string>(3, "sun"));

使用数组方式插入数据:

  1. mapStudent[1] = "zhao";
  2. mapStudent[2] = "qian";
  3. mapStudent[3] = "sun";

说明:上面的两种方法是有区别的,用insert函数插入数据,涉及到集合的唯一性的概念,即当map中有这个关键字时,insert操作是不能实现数据插入的;但是数组方式能够插入数据,插入的数据会覆盖该关键字之前对应的值。

2.2.3 遍历数据

可以通过map的迭代器iterator、调用map对象的begin()和end()函数,实现对于map中数据的遍历操作,示例代码如下:

  1. // 遍历
  2. cout << "content of map as followed: " << endl;
  3. mapStudent_t::iterator iter;
  4. for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  5. {
  6.     cout << iter->first << " " << iter->second << endl;
  7. }

说明:

1)begin()和end()两个成员函数,分别对应map对象中第一个和最后一个数据条目,这两个数据条目的类型是iterator;

2)通过map对象的方法获取到的iterator数据类型是一个“std::pair”对象,iterator数据类型包括下面两个数据:

  • iterator->first: 关键字(key)
  • iterator->second: 存储的数据(value)

2.2.4 查找元素

可以通过使用map的迭代器iterator、调用find函数(传入的参数为要查找的key),来查找具体的元素,示例代码如下:

  1. // 查找
  2. iter = mapStudent.find(2);
  3. if (iter != mapStudent.end())
  4. {
  5. cout << "Find it, the relative value is: " << iter->second << endl;
  6. }
  7. else
  8. {
  9. cout << "Can not find the relative value." << endl;
  10. }

说明:find函数的入参为map的key,并且入参必须完全匹配map的key,才能找到对应元素的value。例如,对于以下map结构:

mapStudent.insert(pair<string, string>("zhao", "zhaoyun"));

如果要查找该map中的元素,必须在find函数中输入完整的key(即“zhao”)才行,如果输入的入参为“zh”、或“zha”,都不能找到该元素。

2.2.5 删除数据

对于map中的数据删除操作,分为以下两种情况:

1)如果想要清空map中的所有数据,可以使用clear函数;

2)如果想要删除map中的指定数据,可以通过使用map的迭代器iterator、调用erase函数来实现,示例代码如下:

  1. // 删除
  2. iter = mapStudent.find(3);
  3. mapStudent.erase(iter);

2.3 示例程序

2.3.1 示例程序1

此处展示一个输出map结构内容的示例代码。代码(map_test1.cpp)内容如下:

  1. #include <iostream>
  2. #include <map>
  3. using namespace std;
  4. int main()
  5. {
  6. // <int, string>结构的map
  7. typedef std::map<int, string> mapStudent_t;
  8. mapStudent_t mapStudent;
  9. mapStudent.insert(pair<int, string>(1, "zhao"));
  10. mapStudent.insert(pair<int, string>(2, "qian"));
  11. mapStudent.insert(pair<int, string>(3, "sun"));
  12. // map简单的输出方法
  13. cout << "mapStudent[1] is: " << mapStudent[1] << endl;
  14. cout << "mapStudent[3] is: " << mapStudent[3] << endl;
  15. // <string, string>结构的map
  16. typedef std::map<string, string> mapRole_t;
  17. mapRole_t mapRole;
  18. mapRole.insert(pair<string, string>("mage", "alliance"));
  19. mapRole.insert(pair<string, string>("paladin", "alliance"));
  20. mapRole.insert(pair<string, string>("warlock", "Horde"));
  21. // map简单的输出方法
  22. cout << "mapRole[\"mage\"] is: " << mapRole["mage"] << endl;
  23. cout << "mapRole[\"warlock\"] is: " << mapRole["warlock"] << endl;
  24. return 0;
  25. }

编译并执行上述代码,结果如下:

2.3.2 示例程序2

示例代码(map_test2.cpp)内容如下:

  1. #include <iostream>
  2. #include <map>
  3. #include <string>
  4. using namespace std;
  5. int main()
  6. {
  7.     typedef std::map<int, string> mapStudent_t;
  8.     mapStudent_t mapStudent;
  9.     mapStudent.insert(pair<int, string>(1, "zhao"));
  10.     mapStudent.insert(pair<int, string>(2, "qian"));
  11.     mapStudent.insert(pair<int, string>(3, "sun"));
  12.     // 遍历
  13.     cout << "content of map as followed: " << endl;
  14.     mapStudent_t::iterator iter;
  15.     for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  16.     {
  17.         cout << iter->first << " " << iter->second << endl;
  18.     }
  19.     // 查找
  20.     iter = mapStudent.find(2);
  21.     if (iter != mapStudent.end())
  22.     {
  23.         cout << "Find it, the relative value is: " << iter->second << endl;
  24.     }
  25.     else
  26.     {
  27.         cout << "Can not find the relative value." << endl;
  28.     }
  29.     // 删除
  30.     iter = mapStudent.find(3);
  31.     mapStudent.erase(iter);
  32.     // 再次遍历,观察删除操作是否成功
  33.     cout << "after delete, content of map as followed: " << endl;
  34.     for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  35.     {
  36.         cout << iter->first << " " << iter->second << endl;
  37.     }
  38.     
  39.     return 0;
  40. }

上述代码运行结果如下:

3 unordered_map

C++标准库提供了四个无序关联容器(unordered associated container),这些容器不是使用比较运算符,而是使用一个哈希函数(hash function)和关键字类型的“==”运算符来组织元素。

在关键字类型的元素没有明显的“序关系”的情况下,无序容器是非常有用的。在某些应用中,维护元素的序的代价非常高昂,此时无序容器也很有用。

unordered_map就是C++标准库提供的四个无序关联容器之一。

3.1 特性

unordered_map的特性如下:

  • 每个关键字(key)只能出现一次;
  • 根据key的哈希值将元素存储在指定位置,因此存储的元素是无序的;
  • 使用哈希表(Hash Table)作为底层数据结构。

3.2 常见用法

3.2.1 构造unordered_map

构造unordered_map的方法如下(以key和value均为char类型为例):

unordered_map<char, char> unoMap;

3.2.2 插入元素

可以通过[]运算符来执行插入元素操作,示例代码如下:

unoMap['a'] = 'b';

说明:如果key对应的value存在,则执行更新元素操作,否则执行添加元素操作。

3.2.3 查找元素

可以通过使用unordered_map的迭代器iterator、调用find函数(传入的参数为要查找的key),来查找具体的元素,示例代码如下:

  1. // 查找
  2. if (mapStudent.find(2) != mapStudent.end())
  3. {
  4. ...
  5. }

此外,也可以通过[]运算符来执行查找元素操作,示例代码如下:

char chValue = unoMap['a'];

3.2.4 计算字符串中各个字符出现的次数

利用unordered_map计算字符串中各个字符出现的次数,示例代码如下:

  1. string strDemo = "aabcccc";
  2. unordered_map<char, int> unoMap;
  3. for (auto ch:strDemo) {
  4.     // unoMap[ch]即为ch字符对应的出现次数
  5.     unoMap[ch]++;
  6. }

3.2.5 查看元素出现的次数

查询某元素在unordered_map中出现的次数,方法如下(返回0或1):

m.count(i)

4 关于有序与无序

STL默认提供的map是“有序”的(即“map”),同时也提供了对应的“无序”版本(即“unordered_map”)。

对于map容器来说,存储于其中的元素是否有序,只会在使用迭代器iterator等场景下对我们有影响,而当我们使用“key-value”获取元素内容时,容器是否有序是无影响的。

下面给出一个简单的示例代码:

  1. #include <map>
  2. #include <unordered_map>
  3. #include <iostream>
  4. using namespace std;
  5. int main()
  6. {
  7. map<int, char> Map;
  8. Map[1] = 'a';
  9. Map[2] = 'b';
  10. Map[3] = 'c';
  11. Map[4] = 'd';
  12. Map[5] = 'e';
  13. cout << "the Map output is: " << endl;
  14. for (auto i = Map.begin(); i != Map.end(); i++) {
  15. std::cout << i->first << ' ' << i->second << std::endl;
  16. }
  17. cout << "Map[2] is: " << Map[2] << endl;
  18. unordered_map<int, char> unoMap;
  19. unoMap[1] = 'a';
  20. unoMap[2] = 'b';
  21. unoMap[3] = 'c';
  22. unoMap[4] = 'd';
  23. unoMap[5] = 'e';
  24. cout << "the unordered_map output is: " << endl;
  25. for (auto i = unoMap.begin(); i != unoMap.end(); i++) {
  26. std::cout << i->first << ' ' << i->second << std::endl;
  27. }
  28. cout << "unoMap[2] is: " << unoMap[2] << endl;
  29. return 0;
  30. }

上方代码的运行结果如下:

从上述代码运行结果可以看出:

  • 当使用迭代器iterator访问map容器中元素时,map与unordered_map结果不同,其中map是有序的,而unordered_map是无序的(似乎是倒序,待确认);
  • 使用下标法获取元素值时,无论map容器中元素是否有序,都可以获取到正确的结果。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/846015
推荐阅读
相关标签
  

闽ICP备14008679号