map和set原理和使用

《C++Primer》中列举了标准库的8个关联容器,这8个容器间的不同体现在三个维度上:
1.或者是一个set,或者是一个map;
2.或者要求不重复的关键字,或者允许重复关键字;
3.按顺序保存,或无序保存。允许重复关键字的容器的名字中都包含单词multi;不保持关键字按顺序存储的容器的名字都以unordered开头。

类型map和multimap定义在头文件map中;set和multiset定义在头文件set中;无序容器定义在头文件unordered_map和unordered_set中。
这里写图片描述
我们介绍两个重要的关联容器map和set

map

map里边存的是一些key-value键值对,其中key起到索引的作用,value表示与索引相关联的数据。map类型也常被称作为关联数组。它和一般数组类似,可以认为key就是数字下标,value就是数组内容,只不过key不一定为整数。

用map来存储每种水果和它的次数,这里的key为string表示水果类型,value为int表示水果出现的次数。此时,每个map中的元素都是一个pair类型的对象,pair是一个模板类型,保存两个public成员first和second分别对应的是key和value。

string strs[] = { "香蕉", "西瓜", "苹果", "梨子" };
     map<string, int> coutMap;
     coutMap.insert(pair<string, int>("香蕉", 1));
     coutMap.insert(pair<string, int>("西瓜", 1));
     coutMap.insert(pair<string, int>("苹果", 3));
     coutMap.insert(pair<string, int>("梨子", 1));

     for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]);++i)
     {
          coutMap[strs[i]]++;
     }

     map<string, int>::iterator it = coutMap.begin();
     while (it != coutMap.end())
     {
          cout <<(*it).first<<":"<<(*it).second << endl;
          //cout << it->first << ":" << (*it).second << endl;
          ++it;
     }

输出结果:
这里写图片描述

set

set里面每个元素只存有一个key,它支持高效的关键字查询操作,例如检查一个关键字是否在set中或者在某些文本处理过程中可用set保存想要忽略的单词。
我们将代码改写为:

string strs[] = { "香蕉", "西瓜", "苹果", "梨子" };
     map<string, int> coutMap;
     set<string> ex = {"西瓜"};
     coutMap.insert(pair<string, int>("香蕉", 1));
     coutMap.insert(pair<string, int>("西瓜", 1));
     coutMap.insert(pair<string, int>("苹果", 3));
     coutMap.insert(pair<string, int>("梨子", 1));

     for (size_t i = 0; i < sizeof(strs) / sizeof(strs[0]);++i)
     {
          if (ex.find(strs[i])==ex.end())
              coutMap[strs[i]]++;
     }

     map<string, int>::iterator it = coutMap.begin();
     while (it != coutMap.end())
     {
          cout <<(*it).first<<":"<<(*it).second << endl;
          //cout << it->first << ":" << (*it).second << endl;
          ++it;
     }

输出结果:
这里写图片描述
通过结果,我们可以看到,当插入key为”西瓜”的键值对的时候,没有插入进去,西瓜的个数还是一开始的1个。其实是set中保存了想要忽略的单词,我们调用了find函数,它返回一个迭代器,如果给定key在set中,则迭代器指向key,否则迭代器返回表示没有找到,只对不在set集合中的单词统计次数。

看到这里,相信大家对map和set都有了一定的了解,map是以key-value的形式存取,set以key的形式存取,底层都是红黑树,因此插入和删除的操作都在O(logn)时间内完成,可以实现高效的插入和删除。

由于底层是红黑树,因此在插入的时候会默认执行排序操作,且key都唯一,从这个角度可以看到,map和set可以实现过滤重复值和排序的功能。

我们再来仔细查看一下打印时候的顺序:
这里写图片描述
大家有没有发现,输出结果是按照ASCLL顺序升序输出的,因此,有的情况下,可以使用map/set排序。

猜你喜欢

转载自blog.csdn.net/zwe7616175/article/details/80090353