参考:

  1. https://blog.csdn.net/shuzfan/article/details/53115922
  2. https://www.nhooo.com/cpp/cpp-map-swap-function.html
  3. https://blog.csdn.net/qq_34106574/article/details/86721916
  4. https://blog.csdn.net/zhongguoren666/article/details/8463249

一、std::map

1. 概述:

STL是标准C++系统的一组模板类,使用STL模板类最大的好处就是在各种C++编译器上都通用。

在STL模板类中,用于线性数据存储管理的类主要有vector、 list,、map 等等。

C++中map提供的是一种键值对容器,里面的数据都是成对出现的,每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。

2. 用法:

(1)声明:

//头文件
#include <map>
//注意,STL头文件没有扩展名.hmap<int, string> ID_Name;// 使用{}赋值是从c++11开始的,因此编译器版本过低时会报错,如visual studio 2012
map<int, string> ID_Name = {{ 2015, "Jim" },{ 2016, "Tom" },{ 2017, "Bob" } };

(2)插入操作:

  • 使用[ ]进行单个插入:
map<int, string> ID_Name;// 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入
ID_Name[2015] = "Tom";
  • 使用insert进行单个和多个插入:
    insert共有4个重载函数:
// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
pair<iterator,bool> insert (const value_type& val);//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排
iterator insert (const_iterator position, const value_type& val);// 插入多个
void insert (InputIterator first, InputIterator last);//c++11开始支持,使用列表插入多个
void insert (initializer_list<value_type> il);

下面是具体使用示例:

#include <iostream>
#include <map>int main()
{std::map<char, int> mymap;// 插入单个值mymap.insert(std::pair<char, int>('a', 100));mymap.insert(std::pair<char, int>('z', 200));//返回插入位置以及是否插入成功std::pair<std::map<char, int>::iterator, bool> ret;ret = mymap.insert(std::pair<char, int>('z', 500));if (ret.second == false) {std::cout << "element 'z' already existed";std::cout << " with a value of " << ret.first->second << '\n';}//指定位置插入std::map<char, int>::iterator it = mymap.begin();mymap.insert(it, std::pair<char, int>('b', 300));  //效率更高mymap.insert(it, std::pair<char, int>('c', 400));  //效率非最高//范围多值插入std::map<char, int> anothermap;anothermap.insert(mymap.begin(), mymap.find('c'));// 列表形式插入anothermap.insert({ { 'd', 100 }, {'e', 200} });return 0;
}

(3)取值:

Map中元素取值主要有at和[ ]两种操作,at会作下标检查,而[]不会。

map<int, string> ID_Name;//ID_Name中没有关键字2016,使用[]取值会导致插入
//因此,下面语句不会报错,但打印结果为空
cout<<ID_Name[2016].c_str()<<endl;//使用at会进行关键字检查,因此下面语句会报错
ID_Name.at(2016) = "Bob";

(4)容量查询:

// 查询map是否为空
bool empty();// 查询map中键值对的数量
size_t size();// 查询map所能包含的最大键值对数量,和系统和应用库有关。
// 此外,这并不意味着用户一定可以存这么多,很可能还没达到就已经开辟内存失败了
size_t max_size();// 查询关键字为key的元素的个数,在map里结果非0即1
size_t count( const Key& key ) const; //

(5)迭代器:

共有八个获取迭代器的函数:begin, end, rbegin, rend 以及对应的 cbegin, cend, crbegin, crend

二者的区别在于:后者一定返回 const_iterator,而前者则根据map的类型返回iterator 或者 const_iterator。const情况下,不允许对值进行修改。如下面代码所示:

map<int,int>::iterator it;map<int,int> mmap;
const map<int,int> const_mmap;it = mmap.begin(); //iterator
mmap.cbegin(); //const_iteratorconst_mmap.begin(); //const_iterator
const_mmap.cbegin(); //const_iterator

返回的迭代器可以进行加减操作,此外,如果map为空,则 begin = end。

(6)删除交换:

  • 删除:
// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器
iterator erase( iterator pos )// 删除一定范围内的元素,并返回一个指向下一元素的迭代器
iterator erase( const_iterator first, const_iterator last );// 根据Key来进行删除,返回删除的元素数量,在map里结果非0即1
size_t erase( const key_type& key );// 清空map,清空后的size为0
void clear();
//clear()就相当于enumMap.erase(enumMap.begin(), enumMap.end());

示例:

enumMap.erase(1);            //删掉关键字“1”对应的条目
enumMap.erase(enumMap.begin());        //删掉第一个条目
enumMap.erase(enumMap.begin(), enumMap.begin() + 1);    //删掉起始的两个条目
  • 交换:
    交换两个map的内容,但是两个map必须是相同类型的,尽管大小可能会有所不同
// 就是两个map的内容互换
void swap( map& other );

示例:
1.

#include <iostream>
#include <map>using namespace std;int main(void) {map<char, int> m1 = {{'a', 1},{'b', 2},{'c', 3},{'d', 4},{'e', 5},};map<char, int> m2;m2.swap(m1);cout << "Map包含以下元素" << endl;for (auto it = m2.begin(); it != m2.end(); ++it)cout << it->first << " = " << it->second << endl;return 0;
}//输出:
Map包含以下元素
a = 1
b = 2
c = 3
d = 4
e = 5

在上面的示例中,Map m1具有五个元素,而m2为空。当您将m1交换为m2时,m1的所有元素都将交换为m2。
2.

#include <iostream>
#include <string>
#include <map>using namespace std;void show(const char *msg, map<string, int> mp);int main() {map<string, int> m1, m2;m1.insert(pair<string, int>("A", 100));m1.insert(pair<string, int>("G", 300));m1.insert(pair<string, int>("B", 200));// 交换m1和m2的内容。cout << "交换m1和m2。\n";m1.swap(m2);show("Contents of m2: ", m2);show("Contents of m1: ", m1);// Clear m1.m1.clear();if(m1.empty()) cout << "m1 为空.";return 0;
}// 使用迭代器显示map<string, int>的内容。
void show(const char *msg, map<string, int> mp) {map<string, int>::iterator itr;cout << msg << endl;for(itr=mp.begin(); itr != mp.end(); ++itr)cout << "  " << itr->first << ", " << itr->second << endl;cout << endl;
}//输出:
交换m1和m2。
m2内容: A, 100B, 200G, 300
m1内容:
m1 为空.

在上面的示例中,Map m1的内容被交换到Map m2,并且在交换Map m1 后已被清除。

(7)顺序比较:

// 比较两个关键字在map中位置的先后
key_compare key_comp() const;

示例:

map<char,int> mymap;
map<char,int>::key_compare mycomp = mymap.key_comp();mymap['a']=100;
mymap['b']=200;
mycomp('a', 'b');  // a排在b前面,因此返回结果为true

(8)查找:

  1. find(key):
// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器
// 根据map的类型,返回的迭代器为 iterator 或者 const_iterator
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;

示例:

std::map<char,int> mymap;
std::map<char,int>::iterator it;mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
mymap['d']=200;it = mymap.find('b');
if (it != mymap.end())mymap.erase (it); // b被成功删除/*find的时候注意key的数据类型,最好用能消除数据类型差异的key,否则可能会出现强制转换后仍找不到的情况。
需要说明的是iterator, begin(), end()是STL模板类的一个通用概念,操作方法也大同小异;
通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator.first 和 iterator.second 分别代表关键字和存储的数据 */
  1. equal_range(key):
iterator map_name.equal_range(key)

equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下,value可插入的第一个位置(亦即lower_bound),j则是在不破坏次序的前提下,value可插入的最后一个位置(亦即upper_bound),因此,[i,j)内的每个元素都等同于value,而且[i,j)是[first,last)之中符合此一性质的最大子区间。

equal_range根据键值,返回一对迭代器的pair对象。如果该键值在容器中存在,则pair对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则pair对象中的两个迭代器都将指向此键应该插入的位置。总之,equal_range返回迭代器位置区间 [ lower_bound, upper_bound )

算法lower_bound返回区间A的第一个迭代器,算法upper_bound返回区间A的最后一个元素的下一个位置,算法equal_range则是以pair的形式将两者都返回

示例:

#include <iostream>
#include <map>
using namespace std;int main ()
{map<char,int> mymap;pair<map<char,int>::iterator,map<char,int>::iterator> ret;mymap['a']=10;mymap['b']=20;mymap['c']=30;ret = mymap.equal_range('b');cout << "lower bound points to: ";cout << ret.first->first << " => " << ret.first->second << endl;cout << "upper bound points to: ";cout << ret.second->first << " => " << ret.second->second << endl;return 0;
}//运行结果:
lower bound points to: 'b' => 20
upper bound points to: 'c' => 30

(9)操作符:

operator:== != < <= > >=
注意:对于==运算符, 只有键值对以及顺序完全相等才算成立。

(10)遍历:

#include<map>
#include<string>
#include<iostream>
using namespace std;int main()
{map<string,int>  m;m["a"]=1;m["b"]=2;m["c"]=3;map<string,int>::iterator it;for(it=m.begin();it!=m.end();++it)cout<<"key: "<<it->first <<" value: "<<it->second<<endl;return   0;
}
map<string,int>::iterator it;   //定义一个迭代指针it。
// it->first 为索引键值,it->second 为值。

在对象中应用时,最好在析构函数中要调用它的clear方法,例如:

class a{map<int,int> m;~a(){m.clear();}
}

二、map 与 multimap 的区别:

map 与 multimap 都是存储key-value(键-值 对)类型的容器。

不同之处在于map只允许key与value一一对应;multimap一个key可对应多个value

示例:
以下不作特别说明,适用于map的都适用于multimap:

#include <opencv2/opencv.hpp>
#include <map>
#include <iostream>
#include <algorithm>    // std::sortusing namespace std;//打印函数可写成模板//打印函数 printfA
void printfA(map<vector<int>, int> vec_)
{for (std::map<std::vector<int>, int>::iterator it = vec_.begin(); it != vec_.end(); it++){std::cout << it->first[0] << "  " << it->first[1] << "  " << it->first[2] << "  " << it->second << std::endl;}cout << "容积 = " << vec_.size() << endl;
}//打印函数 printfB
void printfB(multimap<string, int> vec_)
{for (multimap<string, int>::iterator it = vec_.begin(); it != vec_.end(); it++){std::cout << it->first  << "  " << it->second << std::endl;}cout << "容积 = " << vec_.size() << endl;
}int main()
{//声明,定义std::map<int, std::string> m;m[3] = "h1";m[0] = "what";// 构建 key-valuem.insert(std::pair<int, std::string>(2, "love you"));std::cout << m[0].c_str() << std::endl;//这里数字 不是索引值了std::cout << m[3].c_str() << std::endl;std::cout << m[4].c_str() << std::endl;std::cout << m[2].c_str() << std::endl;   // 会产生一个新的元素,即m[2] = ""m[6] = string("slam2345");std::cout << m.size() << std::endl;       // 5//遍历for (std::map<int, std::string>::iterator it = m.begin(); it != m.end(); it++)std::cout << it->first << ", " << it->second.c_str() << std::endl;std::vector<int> pointTemp;std::map<std::vector<int>, int> vecA;for (int y = 0; y < 4; y++){for (int x = 0; x < 4; x++){pointTemp.push_back(y);pointTemp.push_back(x);pointTemp.push_back(x + y);//插入vecA.insert(std::pair<std::vector<int>, int>(pointTemp, (y * 4 + x + 1)));pointTemp.clear();}}printfA(vecA);

注意区分map与multimap

  1. 两者都会自动排序;
  2. multimap插入不会覆盖已有键值对(对于map若有相同key,则拒绝插入)。
//***************************************************************************************************
//<1>插入返回值 判定是否插入成功//带插入数据vector<int> pointTemp_ = { 1,2,3 }; // Insert方法不能覆盖,如果键已经存在,则插入失败;【注意插入位置,是自动排序】int a1 = 4;//判定插入是否成功pair< map<vector<int>, int>::iterator, bool> isInsertOK;//注意这里声明isInsertOK = vecA.insert(pair<vector<int>, int>(pointTemp_, a1));cout << "插入成功? " << isInsertOK.second << endl;//打印printfA(vecA);//***************************************************************************************************
//<2>map对象的拷贝构造与赋值map<vector<int>, int> vecB(vecA); //拷贝构造map<vector<int>, int> vecC;vecC = vecA;vecC.swap(vecA);//***************************************************************************************************
//<3>查找map<string, int> vecD;// 你以为按照下面初始化 vecD,他的size会是5? 由于insert方法不能覆盖,所以我们将map 改成 multimapvecD.insert(pair<string, int>((string)"china", 1));vecD.insert(pair<string, int>((string)"china", 2));//拒绝插入vecD.insert(pair<string, int>((string)"china", 3));//拒绝插入vecD.insert(pair<string, int>((string)"english", 1));vecD.insert(pair<string, int>((string)"english", 2));//拒绝插入multimap<string, int> vecE;vecE.insert(make_pair((string)"china", 1));vecE.insert(make_pair((string)"china", 1));//允许插入vecE.insert(make_pair((string)"china", 3));//允许插入vecE.insert(make_pair((string)"china", 4));//允许插入vecE.insert(make_pair((string)"china", 5));//允许插入vecE.insert(make_pair((string)"english", 1));vecE.insert(make_pair((string)"english", 2));//允许插入vecE.insert(make_pair((string)"america", 1));vecE.insert(make_pair((string)"america", 2));//允许插入vecE.insert(make_pair((string)"america", 3));//允许插入cout << "multimap 初始化" << endl;cout << "vecE所有元素"<<endl;printfB(vecE);//查找区间multimap<string, int> ::iterator it1 = vecE.lower_bound("china");   //指向vecE中第一个等于键值 “china”对应的元素multimap<string, int> ::iterator it2 = vecE.upper_bound("china");   //指向vecE中第一个大于键值 “china”对应的元素cout << it1->first << " " << it1->second << endl;cout << it2->first << " " << it2->second << endl;// 等于 = lower_bound + upper_boundpair<multimap<string, int>::iterator, multimap<string, int>::iterator > it3 = vecE.equal_range("china");map<string, int>::iterator it4 = it3.first;map<string, int>::iterator it5 = it3.second;//查找key = “china”键值对的个数int iCount = vecE.count("china");//查找key = “china”对应键值对multimap<string, int>::iterator it6 = vecE.find("china");//***************************************************************************************************
// <4>删除multimap<string, int>::iterator itBegin = vecE.begin();// 删除 vecE 前面三个元素 与 后面 三个元素// 在改善特征点匹配算法中有实践int index = 0;int vecA_size = vecE.size();//删除(自定义删除任何元素)for (multimap<string, int>::iterator it_ = vecE.begin(); it_ != vecE.end(); ){//<1>法1//vecE.erase(it_++);//<2>法2if ((0<=index)&&(index<=2)){it_ = vecE.erase(it_);//这样写,防止指针失效}else if (((vecA_size - 3) <= index) && (index <= (vecA_size - 1))){it_ = vecE.erase(it_);}else{it_++;}++index;}//删除multimap中key = "english"的 所有 元素vecE.erase("english");cout << "vecE删除key = english的 所有 元素 " << endl;printfB(vecE);//删除所有元素multimap<string, int>::iterator itBegin_ = vecE.begin();multimap<string, int>::iterator itEnd_ = vecE.end();vecE.erase(itBegin_, itEnd_);//bool isEmpty = vecE.empty();if (vecE.empty()){cout << "vecE已经被清空" << endl;}return 0;
}

【C++】STL map 与 multimap 用法和区别相关推荐

  1. C++ STL map和multimap的简单使用

    #include <iostream> #include <map> using namespace std;typedef pair<int,double> Cu ...

  2. STL 之map,multimap

    头文件: #include <map> map和multimap的唯一区别:map中不可以包含重复键值,而multimap中可以. 构造方法 mType<type1,type2> ...

  3. C++ 笔记(24)— STL map 类(map实例化、插入、查找、删除)

    1. STL 映射类简介 map 和 multimap 是键-值对容器,支持根据键进行查找,区别在于,后者能够存储重复的键,而前者只能存储唯一的键. 为了实现快速查找, STL map 和 multi ...

  4. c++中map、multimap、unordered_map、unordered_multimap的区别

    前言: c++的各种容器使用的时候很方便,但是如果作为一个初学者,看到一堆库要记住也是很头疼的,而且很多库名称会很相似,所以我们要很好的使用这些库的时候,我们需要了解清楚它们底层实现的原理,这样我们使 ...

  5. c++STL容器的Map和multimap

    STL容器的Map和multimap map/multimap的简介 map/multimap对象的默认构造 map的插入与迭代器 迭代器遍历 map对象的拷贝构造与赋值 map的大小 map的删除 ...

  6. C++STL笔记(九):map和multimap详解

    --一个华科大差生的12年程序员工作总结 相关博文:<Essential C++>笔记之关联容器map的使用总结 相关博文:C++<STL和泛型编程>容器不带/带有成员函数总结 ...

  7. C++ map容器和multimap容器(STL map容器)

    目录 1. 关联容器和map容器概述 2. map容器 2.1 map的创建以及初始化列表 2.2 map容器的一般常用属性(方法) 2.3 插入数据 2.4 数据的访问和遍历 2.5 数据的删除 2 ...

  8. Collection,List,Set和Map用法和区别

    Collection,List,Set和Map用法和区别 原创 2009年12月22日 17:05:00 标签: list / hashmap / vector / iterator / object ...

  9. STL中 map 和 multimap

    1. 所在头文件<map>. 命名空间std, 声明如下: 1 namespace std{ 2 template <class Key,class T, 3 class Compa ...

最新文章

  1. 深度学习多变量时间序列预测:GRU算法构建时间序列多变量模型预测交通流量+代码实战
  2. C#应用NPOI实现导出EXcel表格中插入饼状图(可实现动态数据生成)
  3. asp.net多图片上传案例_会计小明的故事-成本核算案例篇
  4. python做动态数据采集仪代理_python做监控数据采集,怎么做.
  5. 剑指offer java 博客_Java--剑指offer(10)
  6. 女员工采购电影票抽中黄金 老板:必须上交 不上交就开除
  7. 2万字总结《MybatisPlus—为简化开发而生》
  8. 人生轨迹的改变,首要在于思维方式的改变。--转贴 CSDN.NET公司内部论坛:迈向成功的“脑力操”...
  9. 多用户访问SSAS cube权限设置
  10. ps2018 html面板,28组经典PS 2018插件合集
  11. Atitit.每周末总结 于每周一计划日程表 流程表 v8 -------------import 上周遗漏日志补充 检查话费 检查流量情况 Crm问候 Crm表total and 问候
  12. GIT GUI(git的可视化工具)
  13. linux软路由 iptv,LEDE x64软路由实现任意网口观看上海电信4K IPTV或上网
  14. BT Openreach批发FTTP网络推出千兆宽带服务
  15. 基于AFD驱动的进程流量控制
  16. 使用Python及SMTP协议发送邮件(以163邮箱为例)
  17. java list 时间排序吗_java collection.sort()根据时间排序list | 学步园
  18. 一个导致ListView中item内容全部重复的可能原因,有点让我啼笑皆非
  19. File::Stamped 时间戳log文件
  20. 测试管理之--团队管理和建设

热门文章

  1. 黄静领29197.14元国家赔偿款 将转赠慈善事业
  2. php怎么打我爱你,教你深情表白:用电影里的方式说“我爱你”
  3. 鼻腔需要每天清洗吗?
  4. 中国和德国屋顶绿化行业的差异对比
  5. 查缺补漏系统学习 EF Core 6 - 数据查询
  6. 计算机网络 | HTTPS | 参考各家资料 | 无知的我学习日记(图文排版无水印)
  7. 关于举办计算机知识讲座的通知,关于举办健康知识讲座的通知
  8. Execl模板导出复杂Execl文件
  9. 内核崩溃捕获机制之kdump详解
  10. 品牌推广别再迷茫,通过这7个步骤,品牌推广成倍增长