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

相关推荐
David猪大卫5 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
HPtiger5 小时前
C++ 入门笔记:从 C 到 C++ 的核心过渡(命名空间、输入输出、缺省参数、重载、引用、内联)
c语言·c++·学习
努力努力再努力wz8 小时前
【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制
c++·junit·lua
慧都产品智能化8 小时前
Qt 表格升级攻略:复用已有编辑器,减少重复开发
c++·qt·编辑器·qt6.3
ShineWinsu9 小时前
对于Qt:QTableWidget常见属性以及QTableWidgetItem类的解析
开发语言·c++·qt·gui·客户端·表格·qtablewidget
ShineWinsu10 小时前
对于Qt:QListWidget常见属性以及QListWidgetItem类的解析
开发语言·c++·qt·客户端·列表·qlistwidget·qlistwidgetitem
坤坤子吖10 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
沫璃染墨11 小时前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
自信1504130575913 小时前
重生之从0开始学习c++之——vector-中篇
c++·学习·算法
ShineWinsu16 小时前
对于Qt:QDial常见属性以及信号的解析
开发语言·c++·qt·gui·客户端·旋钮·qdial