C++:map和unordered_map

最近面试被问到的一个问题,面试当然是挂了,但是收获还是需要分享一下的。

map

  • 底层实现是借助红黑树实现的
  • map插入一个节点的时间复杂度是O(log n)
  • 同样修改一个节点的时间复杂度是O(log n)

关于插入节点的时间复杂度,理解起来很简单,因为变色的时间复杂度是O(1)的,所以插入或者修改只需要找到节点即可,变色时间复杂度是O(1)是因为变色过程与节点数n无关而与节点状态有关。

unordered_map

  • 底层实现是哈希表
  • unordered_map插入一个节点的时间复杂度是O(1)
  • unordered_map修改一个节点的时间复杂度是O(1)

哈希表的结构在STL中有优化,如下图(绘图技术有限),绿色的是指针数组,黄色的是一个链表,绿色的长度应该是一个质数,绿色节点有数据要插入时先判断是否为空不为空就直接头插,为空的话指向虚头然后头插,这样的一种结构使得使用迭代器遍历时更加的高效,同时还减少了虚头节点的使用。

对哈希表来说他会维持一个哈希因子,计算方式很简单:存储节点数/指针数组的长度

当哈希因子到达一个阈值则认为哈希表"满了",然后进行扩容再哈希,这个阈值一般在0.5-1,这保证了哈希表的查询或者插入的时间复杂度可以达到O(1)(当然不考虑极端情况,你n个不同数据的哈希结果映射到了同一个坑里),这些当然都是基础,答上来很简单,注意以下内容。

map和unordered_map的使用情景

map对于每一时刻严格有序的,但是注意它适合小数据量并且节点数据修改不频繁的情况,对于大数据量来说对map可能单层节点需要多个文件页进行存储,你寻找节点时每一次需要产生大量的文件IO,它整体性能甚至低于B树(同等节点红黑树更深),所以对大规模数据时刻要求有序的情况使用B+树更加合适。

节点如果频繁进行修改的情况也是不适合的,因为查找的时间复杂度虽然只有O(log n)但是较于哈希表的O(1)还是太高了,所以一旦数据频繁修改记得用哈希表

那么如果要求有序且可能会进行频繁修改呢?

比如现在有一个排行榜,你会选择哪种数据结构呢?首先对排行榜修改的频率太高了,无论是红黑树还是B+树其实都是不合适的,所以应该使用哈希表存储然后定时刷新,即每过一段时间进行一次外部排序,这样虽然看起来时间复杂度更高了但是实际上更加合理,因为不能只考虑排序而忽略更新的过程。

map底层迭代器

红黑树作为一种有序的树形结构,它的迭代器是通过中序遍历完成创建的,迭代器作为对内存的一种抽象,它存储节点地址和节点信息,在map中维护成了一个链表结构用于进行树的遍历,同时对++/--这些运算符进行重载,重载内部完成迭代器对象间的跳转(pre指向上一个迭代器对象,next指向的是下一个迭代器对象,节点存储的地址是数据的地址)

STL刚开始学,有错误请指出。

相关推荐
王老师青少年编程4 分钟前
csp信奥赛C++高频考点专项训练之贪心算法 --【区间贪心】:雷达安装
c++·算法·贪心·csp·信奥赛·区间贪心·雷达安装
elseif1235 分钟前
分组背包1
c++·学习·算法
Rabitebla11 分钟前
【数据结构】动态顺序表实现详解:从原理到接口设计(面试视角)
c语言·开发语言·数据结构·c++·面试·职场和发展
小明同学0113 分钟前
[C++入门]万字长文梳理 C++11 核心特性
c++
郝学胜-神的一滴20 分钟前
Linux 高并发基石:epoll 核心原理 + LT/ET 触发模式深度剖析
linux·运维·服务器·开发语言·c++·网络协议
Hello!!!!!!25 分钟前
C++基础(六)——数组与字符串
c++·算法
天若有情6731 小时前
反向封神!C++ 全局单例不避反用,实现无锁多线程函数独占访问
java·javascript·c++
智者知已应修善业1 小时前
【51单片机调用__TIME__无法实时时间】2023-7-10
c++·经验分享·笔记·算法·51单片机
凤凰院凶涛QAQ1 小时前
《C++转JAVA快速入手系列》:基本通用语法篇
java·开发语言·c++
Shadow(⊙o⊙)2 小时前
C++常见错误解析2.0
开发语言·数据结构·c++·后端·学习·算法