c++的STL中的map(哈希表)与unordered_map

map:
unordered_map:
map: map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的
unordered_map:unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的

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

1、map简介
map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。
对于迭代器来说,可以修改实值,而不能修改key。

2、map的功能
自动建立Key-value的对应。key 和 value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
快速插入Key -Value 记录。
快速删除记录
根据Key 修改value记录。
遍历所有记录。

3、使用map
使用map得包含map类所在的头文件
#include
#include<bits/stdc++.h>
map对象是模板类,需要关键字和存储对象两个模板参数:
std:map<int,string> personnel;

4、map的构造函数
map共提供了6个构造函数,这块涉及到内存分配器这些东西,略过不表,在下面我们将接触到一些map的构造方法,这里要说下的就是,我们通常用如下方法构造一个map:

map<int, string> mapStudent;

5、数据的插入
在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:

第一种:用insert函数插入pair数据

using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent.insert(map<int, string>::value_type (1, "student_one"));  mapStudent.insert(map<int, string>::value_type (3, "student_two"));  mapStudent.insert(map<int, string>::value_type (2, "student_three"));  map<int, string>::iterator iter;  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  cout<<iter->first<<' '<<iter->second<<endl;  }  

使用迭代器后,是按照字典序来输出的

在这里插入图片描述

//数据的插入--第一种:用insert函数插入pair数据  2个数据组合成一组数据,当需要这样的需求时就可以使用pair,
如stl中的map就是将key和value放在一起来保存。
另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。
pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,
所以可以直接使用pair的成员变量。

第二种:用insert函数插入value_type数据,下面举例说明

//第二种:用insert函数插入value_type数据,下面举例说明  #include <map>  #include <string>  #include <iostream>  using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent.insert(map<int, string>::value_type (1, "student_one"));  mapStudent.insert(map<int, string>::value_type (2, "student_two"));  mapStudent.insert(map<int, string>::value_type (3, "student_three"));  map<int, string>::iterator iter;  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  cout<<iter->first<<' '<<iter->second<<endl;  }  

第三种:用数组方式插入数据,下面举例说明

//第三种:用数组方式插入数据,下面举例说明  #include <map>  #include <string>  #include <iostream>  using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent[1] = "student_one";  mapStudent[2] = "student_two";  mapStudent[3] = "student_three";  map<int, string>::iterator iter;  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  cout<<iter->first<<' '<<iter->second<<endl;  }  

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值

6、map的大小
在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
Int nSize = mapStudent.size();

7、数据的遍历
这里也提供三种方法,对map进行遍历
第一种:应用前向迭代器

第二种:应用反相迭代器

//第二种,利用反向迭代器  #include <map>  #include <string>  #include <iostream>  using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent.insert(pair<int, string>(1, "student_one"));  mapStudent.insert(pair<int, string>(2, "student_two"));  mapStudent.insert(pair<int, string>(3, "student_three"));  map<int, string>::reverse_iterator iter;  for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)  cout<<iter->first<<"  "<<iter->second<<endl;  }  

在这里插入图片描述
第三种,用数组的形式,程序说明如下:

//第三种:用数组方式,程序说明如下  #include <map>  #include <string>  #include <iostream>  using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent.insert(pair<int, string>(1, "student_one"));  mapStudent.insert(pair<int, string>(2, "student_two"));  mapStudent.insert(pair<int, string>(3, "student_three"));  int nSize = mapStudent.size();  //此处应注意,应该是 for(int nindex = 1; nindex <= nSize; nindex++)  
//而不是 for(int nindex = 0; nindex < nSize; nindex++)  for(int nindex = 1; nindex <= nSize; nindex++)  cout<<mapStudent[nindex]<<endl;  }  

8、查找并获取map中的元素(包括判定这个关键字是否在map中出现)

第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了

第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器。查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.

#include <map>  #include <string>  #include <iostream>  using namespace std;  int main()  {  map<int, string> mapStudent;  mapStudent.insert(pair<int, string>(1, "student_one"));  mapStudent.insert(pair<int, string>(2, "student_two"));  mapStudent.insert(pair<int, string>(3, "student_three"));  map<int, string>::iterator iter;  iter = mapStudent.find(1);  if(iter != mapStudent.end())  cout<<"Find, the value is "<<iter->second<<endl;  else  cout<<"Do not Find"<<endl;  return 0;  
}  

在这里插入图片描述
9、从map中删除元素
移除某个map中某个条目用erase()

mapStudent.erase(iter);  如果要删除1,用关键字删除  int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0  用迭代器,成片的删除  一下代码把整个map清空  mapStudent.erase( mapStudent.begin(), mapStudent.end() );  成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合  自个加上遍历代码,打印输出吧  

10、map中的swap用法
map中的swap不是一个容器中的元素交换,而是两个容器所有元素的交换。

11、排序-map中的sort问题
map中的元素是自动按Key升序排序,所以不能对map用sort函数;

12、map的基本操作函数:
C++ maps是一种关联式容器,包含“关键字/值”对

begin()         返回指向map头部的迭代器clear()        删除所有元素count()         返回指定元素出现的次数empty()         如果map为空则返回trueend()           返回指向map末尾的迭代器equal_range()   返回特殊条目的迭代器对erase()         删除一个元素find()          查找一个元素get_allocator() 返回map的配置器insert()        插入元素key_comp()      返回比较元素key的函数lower_bound()   返回键值>=给定元素的第一个位置max_size()      返回可以容纳的最大元素个数rbegin()        返回一个指向map尾部的逆向迭代器rend()          返回一个指向map头部的逆向迭代器size()          返回map中元素的个数swap()           交换两个mapupper_bound()    返回键值>给定元素的第一个位置value_comp()     返回比较元素value的函数

map:

  1、优点:(1)有序性:map结构的红黑树自身是有序的,但是要中序遍历输出(2)时间复杂度低:内部结构时红黑树,红黑树很多操作都是在logn的时间复杂度下实现的,因此效率高。2、缺点:空间占有率高,因为map内部实现是红黑树,虽然它时间复杂度低,运行效率高,但是因为每一个节点都需要额外保存父  节点、孩子节点和红黑树性质,这样使得每一个节点都占用大量的空间。3、应用场景:应用于对顺序有要求的问题,用map会更高效。

unordered_map:

 1、优点:内部结构是哈希表,查找为O(1),效率高。2、缺点:哈希表的建立耗费时间。3、应用场景:  对于频繁查找的问题,用unordered_map更高效。

总结:

  1、内存占用率问题转化为 红黑树 VS 哈希表,还是unordered_map内存占用高。2、但是unordered_map执行效率高。3、对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。

map和unordered_map的使用
unordered_map与map用法一致,里面的元素以pair类型存储。虽然底层实现完全不同,但是外部使用一致。

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

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

相关文章

IdentityServer4系列 | 简化模式

一、前言从上一篇关于资源密码凭证模式中&#xff0c;通过使用client_id和client_secret以及用户名密码通过应用Client(客户端)直接获取&#xff0c;从而请求获取受保护的资源&#xff0c;但是这种方式存在client可能存了用户密码这不安全性问题&#xff0c;所以需要做到client…

char截取字符串_字符串的排列(滑动窗口)

题目&#xff1a;给定两个字符串 s1 和 s2&#xff0c;写一个函数来判断 s2 是否包含 s1 的排列。换句话说&#xff0c;第一个字符串的排列之一是第二个字符串的子串。示例1&#xff1a;输入: s1 "ab" s2 "eidbaooo"输出: True解释: s2 包含 s1 的排列之…

c++中的全排列函数next_permutation()

全排列函数next_permutation() prev_permutation函数&#xff08;按降序排序&#xff09; 计算序列全排列的函数&#xff1a;next_permutation&#xff08;start,end&#xff09;&#xff0c;此函数求的是当前排列的下一个排列&#xff0c;这里的“下一个”&#xff0c;我们可…

学习搭建 Consul 服务发现与服务网格-有丰富的示例和图片

第一部分&#xff1a;Consul 基础1&#xff0c;Consul 介绍官网文档描述&#xff1a;Consul 是一个网络工具&#xff0c;提供功能齐全的服务网格和服务发现。它可以做什么&#xff1a;自动化网络配置&#xff0c;发现服务并启用跨任何云或运行时的安全连接。那么&#xff0c;我…

多线程并发如何高效实现生产者/消费者?

【导读】无需引入第三方消息队列组件&#xff0c;我们如何利用内置C#语法高效实现生产者/消费者对数据进行处理呢&#xff1f;在.NET Core共享框架&#xff08;Share Framework&#xff09;引入了通道&#xff08;Channel&#xff09;&#xff0c;也就是说无需额外通过NuGet包安…

js-cookie 无法设置cookie_php操作 cookie

1&#xff0c;设置cookie<?phpsetcookie(key);setcookie(key1,value1);setcookie(key2,value2,time()1*24*60*60);setcookie(key4, value4, time() 1 * 24 * 60 * 60, , , false, true); //一旦cookie的httponly为真&#xff0c;那么只能在服务端获取&#xff0c;js无法操…

.Net orm 开源项目 FreeSql 2.0.0

写在开头2018年11月头脑发热到今天&#xff0c;一晃已经两年&#xff0c;当初从舒服区走向一个巨大的坑&#xff0c;回头一看后背一凉。两年时间从无到有&#xff0c;经历数不清的日夜奋斗&#xff08;有人问花了多长时间投入&#xff0c;答案&#xff1a;全职x2 两年无休息&a…

c语言函数库——ispunct函数 判断字符是否为标点符号或特殊字符

c语言函数库——ispunct函数 判断字符是否为标点符号或特殊字符 头文件&#xff1a;#inlude <ctype.h> spunct() 函数用来检测一个字符是否为标点符号或特殊字符&#xff0c;其原型为&#xff1a; int ispunct(int c); 【参数】c 为需要检测的字符。 【返回值】若 c 为标…

js重新渲染div_前端工程师必备:从浏览器的渲染到性能优化

文章来自&#xff1a;华为云开发者社区摘要&#xff1a;本文主要讲谈及浏览器的渲染原理、流程以及相关的性能问题。问题前瞻1. 为什么css需要放在头部&#xff1f;2. js为什么要放在body后面&#xff1f;3. 图片的加载和渲染会阻塞页面DOM构建吗&#xff1f;4. dom解析完才出现…

做架构也得讲武德

这里是Z哥的个人公众号每周五11&#xff1a;45 按时送达当然了&#xff0c;也会时不时加个餐&#xff5e;我的第「169」篇原创敬上大家好&#xff0c;我是Z哥。今天分享一篇对「架构」这件事的随想。我想&#xff0c;做「架构」是每个热爱技术的技术人在不断追求想进入的领域。…

c++随机数函数rand()

c 语言rand()生成随机数 c语言中rand()函数生成随机数的用法&#xff1a; 详细介绍&#xff1a; (1)使用该函数首先应在开头包含头文件stdlib.h #include<stdlib.h>(C建议使用#include&#xff0c;下同) (2)在标准的C库中函数rand()可以生成0~RAND_MAX之间的一个随机数…

杂牌手柄模拟xboxone手柄_手机就能玩Switch游戏,蛋蛋模拟器+盖世小鸡X2手柄体验...

最近收到一个很爆炸的消息&#xff0c;国外大神开发出了EGG模拟器(蛋蛋模拟器)&#xff0c;让手机也能玩Switch游戏&#xff0c;一直垂涎Switch游戏体验的我怎么能错过呢&#xff0c;必须一探究竟。据悉&#xff0c;EGG模拟器支持100多款Switch游戏&#xff0c;而且游戏还在持续…

api-hook,更轻量的接口测试工具

前言在网站的开发过程中&#xff0c;接口联调和测试是至关重要的一环&#xff0c;其直接影响产品的核心价值&#xff0c;而目前也有许多技术方案和工具加持&#xff0c;让我们的开发测试工作更加便捷。接口作为数据传输的重要载体&#xff0c;数据格式和内容具有多样性&#xf…

C++11的for循环使用auto的新用法

C11的for循环使用auto的新用法 for(auto a:vec) { cout<<a<<" "; } #include<bits/stdc.h> using namespace std; int main() {vector<int> vec;for(int i0; i<10; i){vec.push_back(i);}for(auto a:vec){cout<<a<<" …

如何使用 C# 中的 HashSet

译文链接&#xff1a;https://www.infoworld.com/article/3586972/how-to-use-hashset-in-csharp.htmlHashSet 是一个优化过的无序集合&#xff0c;提供对元素的高速查找和高性能的set集合操作&#xff0c;而且 HashSet 是在 .NET 3.5 中被引入的&#xff0c;在 System.Collect…

python装饰器源代码_13-Python-装饰器

1、装饰器的定义 装饰器的本质就是函数&#xff0c;用来装饰其它函数&#xff0c;就是为其它函数添加附加功能。 装饰器原则如下&#xff1a; 不能修改被装饰的函数的源代码 不能修改被装饰的函数的调用方式 2、实现装饰器知识储备 函数即变量 1 defbar():2 print("in the…

算法设计与分析——分治与递归策略——hanoi问题

**汉诺塔问题&#xff1a;**古代有一个梵塔&#xff0c;塔内有三个座A、B、C&#xff0c;A座上有64个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上&#xff08;如图&#xff09;。有一个和尚想把这64个盘子从A座移到B座&#xff0c;但每次只能允许移…

post多个参数_关于HTTP GET和POST的区别

Photo by Luca Bravo on UnsplashGET还是POST&#xff1f; 考虑将浏览器作为客户端&#xff0c;可以缓存哪种方法&#xff1f; 哪个是"安全"方法&#xff1f; 哪一个不是幂等的&#xff1f; 如果我将端点URL复制并粘贴到浏览器的地址栏中&#xff0c;然后按Enter&…

小试YARP

.net core下&#xff0c;一个轻量组反向代理库&#xff0c;由微软发起。做了一个简单的带验证的反向代理&#xff0c;应用结构如上图&#xff0c;一个验证服务&#xff0c;两个业务服务和一个YARP服务。源码https://github.com/axzxs2001/Asp.NetCoreExperiment/tree/master/As…

Entity Framework Core 5中实现批量更新、删除

本文介绍了一个在EntityFramework Core 5中不需要预先加载数据而使用一句SQL语句批量更新、删除数据的开发包&#xff0c;并且分析了其实现原理&#xff0c;并且与其他实现方案做了比较。一、背景随着微软全面拥抱开源&#xff0c;.Net开源社区百花开放&#xff0c;涌现了非常多…