STL:关联式容器&哈希

关联式容器
底层结构有两种—红黑树和哈希(哈希后面讲)
map,set,multimap,multiset
相同点:

  • 底层结构相同—红黑树,红黑树是二叉搜索树+条件限制
  • 查询时间复杂度是O(logN)
  • 使用迭代器遍历(中序遍历规则)都会得到一个关于key的有序序列
  • 默认按照less方式比较–升序序列
  • 所有key不能修改—如果修改,必须先删除后插入
  • 查找规则相同:按照二叉搜索树的规则进行查找

不同点:

  • 存储元素类型不同
    map:kv模型的键值对,key唯一
    set:k模型—key就是val,val就是key
    multimap:kv模型的键值对,key可以重复
    multiset:

map

在这里插入图片描述

在这里插入图片描述

multimap没有[]操作,因为有多个key,不知道返回谁的val

set

功能:去重+排序
向set中插入很多数据后,set会自动去除

所有multiset功能就剩排序了

哈希

在查找元素时不比较元素

  • 方法:在存储元素时,通过某种机制让元素与其存储位置建立一一对应的关系,则查找时几乎就不需要比较了
  • 插入:通过函数(数学中的函数式)计算数据在表格中的位置
    再插入

函数就称为哈希函数,表称为哈希表

缺陷:不同的元素通过相同的哈希函数,算出了相同的哈希地址

常见函数
直接定值:关于元素k的一元一次函数
除留取余: Hash(key) = key% p(p<=m), p最好是一个不超m的最大的一个素数

真正解决哈希冲突的方式

闭散列

从哈希冲突的位置开始找“下一个非空的位置

线性探测:从发生冲突的位置依次向后找,如果查找到空间末尾,也没有发现空位置,再折回到空间起始位置继续查找,直到找到空位置

  • 问题:
    如何知道这个位置上有没有元素
  • 解决:
    给每个空间一个标记:EMPTY,EXIST,DELETE
  • 查找:
    通过哈希函数计算元素在表中的位置,检测位置是否是空
  • 插入:
    通过哈希函数计算插入的位置,检测该位置是否发生冲突
    没有发生插入,并修改状态
    发生冲突,找到下一个空位置插入
  • 删除:
    通过哈希函数计算删除的位置,检测位置是否为空
    空则元素不存在
    非空检测是否是待删除元素(删除就修改状态为DELETE,不能直接改成空)

线性探测的缺陷:容易产生数据堆积—发生冲突,冲突的元素容易连成一片

二次探测:H(i)=(H(0) + i^2)%表格容量
i表示探测次数

  • 插入
    计算哈希地址
    检测位置是否为空
    空—直接插入—修改状态为EXIST
    非空–发生冲突—二次探测

二次探测缺陷:表格中空位置少的时候,会找很多次
解决方式:达到一定程度就进行扩容

这个程度就的负载因子=元素个数/表格容量
线性探测控制到70%
二次探测控制到50-60%
空间换时间的方法

开散列–链地址法

将发生冲突的元素用单链表链接起来
实质是数组+链表的集合
每个链表称为桶

冲突元素多了,哈希桶就退化成链表了
最理想的状态是哈希桶中,桶的个数和元素的个数相等,也就是每个数组元素下只有一个链表
扩容之后哈希桶容量改变了,哈希函数就变了

如果一个桶中出现很多节点,就要将其转换成红黑树,不然查找效率太低了

再散列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值