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刚开始学,有错误请指出。

相关推荐
何曾参静谧25 分钟前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
AI街潜水的八角34 分钟前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
JSU_曾是此间年少1 小时前
数据结构——线性表与链表
数据结构·c++·算法
此生只爱蛋2 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
何曾参静谧2 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu3 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
ULTRA??4 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者4 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者4 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>5 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode