STL之map与pair与unordered_map常用函数详解

一、map的概述

map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

下面举例说明:

众所周知,在定义数组的时候比如(int array[10]) ,array[0]=25,array[1]=10,其实就是一个映射,将0—>25,1—>10,就是将0映射到25,将1映射到10,这种一一对应的关系就是映射,就数组来说,他的下标和其下标所对应的值就是一种映射关系,但是这一种关系比较死板,于是就有map,这一种容器,map可以建立将任何基本类型(包括STL容器)映射到任何基本数据类型(包括STL容器)

二、map的定义与初始化(插入)

  • 单独定义一个map:
//  引入一个头文件
#include <map>
map<typename1,typename2> mp;
  • typename1是键值的数据类型

  • typename2是值的数据类型

  • 如果是字符串映射到整型数组,键值必须使用string类型,而不能使用char数组。

    这是因为char作为数组,不能作为键值。

  • map的键和值可以是STL的容器,我们将set映射到一个字符串

map<set<int>,string> mp;

三、map的元素的访问

  • map中的容器值可以通过:下标和迭代器进行访问。
  • 下标访问map键值是唯一的
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<char,int> mp;
mp['c']=20;
mp['c']=30; // 由于键值唯一,第一个他的值将会被覆盖
cout<<mp['c']<<endl;
return 0;
}
// 输出
30
  • 通过迭代器访问

    map的迭代器与其他STL容器相同

map<typename1,typename2>::iterator it;
// 由于一个it对应两个值,我们使用 it->first 访问键 it->second 访问值
  • 下面来看一个示例:

    PS:下面我以3种不同的方式进行插入不懂得可以参照这一篇文章:

//   以类似数组的的表达方式来进行
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<char,int> mp;
char key;
int val;
int t=5;
while(t--)
{
cin>>key>>val;
mp[key]=val;
}
// 通过迭代器来访问
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
} a 5
s 8
z 6
p 3
t 7 a 5
p 3
s 8
t 7
z 6

其实细心的小伙伴已经发现,其输出结果是按照键值进行升序排序的。C++11中有unordered_map,以散列来代替map内部的红黑树实现,其不需要排序速度就 快很多了。下面会有介绍。

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<char,int> mp;
char key;
int val;
int t=5;
while(t--)
{
cin>>key>>val;
mp.insert(make_pair(key,val)); // 以make_pair来插入
}
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<char,int> mp;
char key;
int val;
int t=5;
while(t--)
{
cin>>key>>val;
mp.insert(pair<char,int>(key,val)); // 以pair来插入
}
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<char,int> mp;
char key;
int val;
int t=5;
while(t--)
{
cin>>key>>val;
mp.insert(pair<char,int>(key,val));
}
// 这种基于范围的for循环,只有C++11以上才可以
for(auto it=mp.begin();it!=mp.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
  • 用insert函数插入value_type数据,下面举例说明
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student2"));
for(map<int,string>::iterator it=mapStudent.begin();it!=mapStudent.end();it++)
cout<<it->first<<" "<<it->second<<endl;
return 0;
} // 输出结果:
G:\clion\qifei\cmake-build-debug\qifei.exe
1 student1
2 student2
3 student2 Process finished with exit code 0

四.map常用函数解析

  • find()用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student2"));
map<int,string>::iterator pter=mapStudent.find(2);
cout<<pter->first<<" "<<pter->second<<endl;
return 0;
}
// 输出结果:
2 student2
  • erase()删除元素有两种方法:删除单个元素;删除一个区间的元素。

    1. 删除单个元素:

      • mp.erase(it), it为要删除的元素的迭代器

        #include <iostream>
        #include <map>
        #include <string>
        using namespace std;
        int main() {
        map<int, string> mapStudent;
        mapStudent.insert(map<int,string>::value_type(1,"student1"));
        mapStudent.insert(map<int,string>::value_type(2,"student2"));
        mapStudent.insert(map<int,string>::value_type(3,"student2"));
        map<int,string>::iterator pter=mapStudent.find(2);
        mapStudent.erase(pter);
        for(map<int,string>::iterator it=mapStudent.begin();it!=mapStudent.end();it++)
        cout<<it->first<<" "<<it->second<<endl;
        return 0;
        } // 输出结果:
        1 student1
        3 student2
        • 通过键值来删除一个元素:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student2"));
map<int,string>::iterator pter=mapStudent.find(2);
mapStudent.erase(2);
for(map<int,string>::iterator it=mapStudent.begin();it!=mapStudent.end();it++)
cout<<it->first<<" "<<it->second<<endl;
return 0;
} // 输出结果:
1 student1
3 student2

2.erase(first,last),可以删除整个区间的元素;删除区间为[first,last)。

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student3"));
mapStudent.insert(map<int,string>::value_type(4,"student4"));
mapStudent.insert(map<int,string>::value_type(5,"student5"));
mapStudent.insert(map<int,string>::value_type(6,"student6"));
mapStudent.insert(map<int,string>::value_type(7,"student7"));
map<int,string>::iterator pter=mapStudent.find(4);
mapStudent.erase(pter,mapStudent.end());
for(map<int,string>::iterator it=mapStudent.begin();it!=mapStudent.end();it++)
cout<<it->first<<" "<<it->second<<endl;
return 0;
} // 输出结果:
1 student1
2 student2
3 student3
  • size() ,可以获取map中的映射对数。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student3"));
mapStudent.insert(map<int,string>::value_type(4,"student4"));
mapStudent.insert(map<int,string>::value_type(5,"student5"));
mapStudent.insert(map<int,string>::value_type(6,"student6"));
mapStudent.insert(map<int,string>::value_type(7,"student7"));
cout<<mapStudent.size()<<endl;
return 0;
} // 输出结果:
7
  • clear(),请空所有的元素。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<int, string> mapStudent;
mapStudent.insert(map<int,string>::value_type(1,"student1"));
mapStudent.insert(map<int,string>::value_type(2,"student2"));
mapStudent.insert(map<int,string>::value_type(3,"student3"));
mapStudent.insert(map<int,string>::value_type(4,"student4"));
mapStudent.insert(map<int,string>::value_type(5,"student5"));
mapStudent.insert(map<int,string>::value_type(6,"student6"));
mapStudent.insert(map<int,string>::value_type(7,"student7"));
mapStudent.clear();
cout<<mapStudent.size()<<endl;
return 0;
} // 输出结果:
0

map和unordered_map(c++11)的使用

unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的

map和unordered_map的差别

需要引入的头文件不同

map: #include < map >
unordered_map: #include < unordered_map >

内部实现机理不同

map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。

unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。哈希表详细介绍

优缺点以及适用处

map:

优点:

有序性,这是map结构最大的优点其元素的有序性在很多应用中都会简化很多的操作

红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高

缺点:空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间

适用处:对于那些有顺序要求的问题,用map会更高效一些

unordered_map:

优点: 因为内部实现了哈希表,因此其查找速度非常的快

缺点: 哈希表的建立比较耗费时间

适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map

总结:

内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。

但是unordered_map执行效率要比map高很多

对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int main() {
unordered_map<int, string> mapStudent;
mapStudent.insert(unordered_map<int,string>::value_type(2,"student2"));
mapStudent.insert(unordered_map<int,string>::value_type(4,"student4"));
mapStudent.insert(unordered_map<int,string>::value_type(5,"student5"));
mapStudent.insert(unordered_map<int,string>::value_type(3,"student3"));
mapStudent.insert(unordered_map<int,string>::value_type(7,"student7"));
mapStudent.insert(unordered_map<int,string>::value_type(6,"student6"));
mapStudent.insert(unordered_map<int,string>::value_type(1,"student1"));
for(auto it=mapStudent.begin();it!=mapStudent.end();it++)
cout<<it->first<<" "<<it->second<<endl;
return 0;
} // 输出结果:
G:\clion\qifei\cmake-build-debug\qifei.exe
1 student1
6 student6
7 student7
2 student2
4 student4
5 student5
3 student3 Process finished with exit code 0

STL之map与pair与unordered_map常用函数详解的更多相关文章

  1. php缓存技术——memcache常用函数详解

    php缓存技术——memcache常用函数详解 2016-04-07 aileen PHP编程 Memcache函数库是在PECL(PHP Extension Community Library)中, ...

  2. # OpenGL常用函数详解(持续更新)

    OpenGL常用函数详解(持续更新) 初始化 void glutInit(int* argc,char** argv)初始化GULT库,对应main函数的两个参数 void gultInitWindo ...

  3. jQuery数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解

    1. $.each(array, [callback]) 遍历[常用] 解释: 不同于例遍jQuery对象的$().each()方法,此方法可用于例遍任何对象.回调函数拥有两个参数:第一个为对象的成员 ...

  4. oracle常用函数详解(详细)

    转自:https://www.cnblogs.com/lxl57610/p/7442130.html Oracle SQL 提供了用于执行特定操作的专用函数.这些函数大大增强了 SQL 语言的功能.函 ...

  5. Discuz 插件制作之后台常用函数详解

    目录 showsetting()表单显示 cpmsg()提示消息 showformheader()创建表单头 showformfooter()创建表单尾 showtableheader()创建表格头 ...

  6. numpy.random 常用函数详解之排列乱序篇(Permutations)

    1.numpy.random.shuffle(x) 参数:填入数组或列表. 返回值:无. 函数功能描述:对填入的数组或列表进行乱序处理,shape保持不变. 2.numpy.random.permut ...

  7. numpy.random 常用函数详解之简单随机数篇(Simple random data)

    1.numpy.random.rand(d0,d1,d2,...,dn) 参数:d0,d1,d2,...,dn 须是正整数,用来描述生成随机数组的维度.如(3,2)代表生成3行2列的随机数组. 返回值 ...

  8. DB2常用函数详解(一):字符串函数

    VALUE函数 语法:VALUE(EXPRESSION1,EXPRESSION2) VALUE函数是用返回一个非空的值,当其第一个参数非空,直接返回该参数的值,如果第一个参数为空,则返回第一个参数的值 ...

  9. Python os模块常用函数详解

    当前使用平台: os.name #返回当前使用平台的代表字符,Windows用'nt'表示,Linux用'posix'表示 当前路径和文件 os.getcwd() #返回当前工作目录 os.listd ...

随机推荐

  1. LSP原则—关于正方形不是长方形

    长方形有二个属性长和宽.并有一个设置长的方法和设置宽的方法,还有一个求面积的方法. 像下面 private int length; private int width; public void set ...

  2. 如何优雅的使用AbpSettings

    在Abp中配置虽然使用方便,但是每个配置要先定义key,要去provider中定义,再最后使用key从ISetting中获取还是挺麻烦的一件事, 最主要是获取修改的时候,比如,修改用户配置,是从获取一 ...

  3. 解决unrecognized import path "xxx"

    $ export GOPROXY=https://goproxy.io 环境变量配置上面这句即可 https://goproxy.io 是一个goproxy.io这个开源项目提供的公开代理服务. 使用 ...

  4. 会话存储sessionStorage

    会话存储的工作方式和本地存储的工作方式很接近,不同之处在于数据是各个浏览器上下文私有的,会在文档被关闭时移除(注意是被关闭时才移除,刷新是不会移除的).我们通过全局sessionStorage访问会话 ...

  5. Python生态_turtle库

    Python生态_turtle库: 绘制状态函数: pendown():别名pd(),落下画笔,之后,移动画笔将绘制形状 penup():抬起画笔 pensize():画笔粗细大小 颜色控制函数: p ...

  6. 0919-The Standard of Code Review

    The primary purpose of code review is to make sure that the overall code health of Google’s code bas ...

  7. 从发布订阅模式入手读懂Node.js的EventEmitter源码

    前面一篇文章setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop详细讲解了浏览器和Node.js的异步API及其底层原理Event Loop.本文会讲一下不 ...

  8. [BJDCTF 2nd]old-hack

    进入首页: 首页告诉了我们是thinkphp5的漏洞. 知道了是哪个版本的话就搜一搜喽:最后发现是thinkphp5.0.23的命令执行 payload_1:查看根目录文件,发现flag位置 http ...

  9. css第二波

    目录 css第二波 盒子模型 浮动 三种取值 清除浮动 浮动页面布局 溢出 定位 相对定位 relative(相对定位) 绝对定位 absolute(绝对定位) 固定定位 fixed(固定) 模糊框 ...

  10. div 3 frog jump

    There is a frog staying to the left of the string s=s1s2…sn consisting of n characters (to be more p ...