数据结构-哈希表

哈希存储(散列存储) 多考虑查找
经过特殊处理(哈希函数)映射到某一个位置上
记录下的数据---->哈希函数(f(key))----->存储位置

哈希冲突:当经过计算不能每个都完全散列存储

好处:如果哈希冲突较少的话相比于数组寻找是有提高的(以O(1)复杂度)

如何尽可能避免哈希冲突的产生:
解决方法:
1.开放地址法
当经过计算映射到相同位置时,检测到这个位置已经存储到数据时,
从这个位置向下去找没有存储数据的单元
2.链地址法
在哈希表中,不再进行原记录的一个存储,
而是存储原纪录要存储数据的地址
扩展:
如果冲突的很多,
那这个增加的链表很长处理方法:
举个例子:拿Java集合类中的HashMap来说
如果这个链表的长度大于等于8的话链表就会转化为树结构
当然如果长度小于等于6的话就会还原链表,以此来解决链表过长导致的性能问题
这样设计是因为中间有个7作为一个差值,来避免频繁的进行树和链表的转换
因为频繁转换也是影响性能的

可能也会考虑到如果一直找不到空的位置,
但找不到空的位置的前提是位置已经被占光了
但是实际情况是位置不会被占光,因为有一定量的位置被占了的时候就会发生扩容
当哈希表被占的位置比较多的时候,出现哈希冲突的概率也就变高了所以很有必要进行扩容
扩容方法:
这里一般有一个增长因子的概念,也叫做那个负载因子
简单点来说就是已经被占的位置与总位置的一个百分比
比如一共十个位置,现在已经占了七个位置,就触发了扩容机制,因为它的增长因子是0.7
也就是达到了总位置的百分之七十就需要扩容
还拿HashMap来说,当它当前的容量占总容量的百分之七十五的时候就需要扩容了
而且这个扩容也不是简单的把数组扩大,而是新创建一个数组是原来的两倍
然后把原数组的所有Entry都重新Hash一遍放到新的数组
因为数组扩大了,所以一般哈希函数也会有变化,
这里的Hash也就是把之前的数据通过新的哈希函数计算出新的位置来存放

(声明不能初始化!)

设计哈希函数时尽量使数据均匀分布
1.创建哈希表
2.设计哈希函数
3.数据插入
通过设计好的哈希函数获得该数据在哈希表这个数组中的地址
4.数据查找
哈希表的遍历本质上就是多条链表的遍历(数组中的每条链表)
查找节点:
1.定位到哈希表的那条链表
2.进行链表的遍历
5.销毁
如果在创建哈希表时没有申请空间而是定义的全局变量则不用自己回收
如果定义了则找到每条链表,之后销毁

哈希存储(散列存储) 多考虑查找
经过特殊处理(哈希函数)映射到某一个位置上
记录下的数据---->哈希函数(f(key))----->存储位置

哈希冲突:当经过计算不能每个都完全散列存储

好处:如果哈希冲突较少的话相比于数组寻找是有提高的(以O(1)复杂度)

如何尽可能避免哈希冲突的产生:
解决方法:
1.开放地址法
当经过计算映射到相同位置时,检测到这个位置已经存储到数据时,
从这个位置向下去找没有存储数据的单元
2.链地址法
在哈希表中,不再进行原记录的一个存储,
而是存储原纪录要存储数据的地址
扩展:
如果冲突的很多,
那这个增加的链表很长处理方法:
举个例子:拿Java集合类中的HashMap来说
如果这个链表的长度大于等于8的话链表就会转化为树结构
当然如果长度小于等于6的话就会还原链表,以此来解决链表过长导致的性能问题
这样设计是因为中间有个7作为一个差值,来避免频繁的进行树和链表的转换
因为频繁转换也是影响性能的

可能也会考虑到如果一直找不到空的位置,
但找不到空的位置的前提是位置已经被占光了
但是实际情况是位置不会被占光,因为有一定量的位置被占了的时候就会发生扩容
当哈希表被占的位置比较多的时候,出现哈希冲突的概率也就变高了所以很有必要进行扩容
扩容方法:
这里一般有一个增长因子的概念,也叫做那个负载因子
简单点来说就是已经被占的位置与总位置的一个百分比
比如一共十个位置,现在已经占了七个位置,就触发了扩容机制,因为它的增长因子是0.7
也就是达到了总位置的百分之七十就需要扩容
还拿HashMap来说,当它当前的容量占总容量的百分之七十五的时候就需要扩容了
而且这个扩容也不是简单的把数组扩大,而是新创建一个数组是原来的两倍
然后把原数组的所有Entry都重新Hash一遍放到新的数组
因为数组扩大了,所以一般哈希函数也会有变化,
这里的Hash也就是把之前的数据通过新的哈希函数计算出新的位置来存放

(声明不能初始化!)

设计哈希函数时尽量使数据均匀分布
1.创建哈希表
2.设计哈希函数
3.数据插入
通过设计好的哈希函数获得该数据在哈希表这个数组中的地址
4.数据查找
哈希表的遍历本质上就是多条链表的遍历(数组中的每条链表)
查找节点:
1.定位到哈希表的那条链表
2.进行链表的遍历
5.销毁
如果在创建哈希表时没有申请空间而是定义的全局变量则不用自己回收
如果定义了则找到每条链表,之后销毁

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值