如何设计散列函数
-
散列函数的目标\
- 散列函数不能台复杂
- 散列函数生成的值要随机并且均匀
-
散列方法
- 直接寻址法
- 平法取中法
- 折叠法
- 随机数法
- ....
装载因子过大怎么办?
-
装载因子过大
-
当装载因子达到一定的阈值后,说明hash冲突严重,插入和查询耗时都会增加,需要动态扩容
-
动态扩容会导致位置发生变化
-
动态扩容的时间复杂度 均摊后是O(1)
- 只有最坏是O(n),其余时候为O(1)
-
-
装载因子过小
- 可以考虑动态缩容
如何避免低效扩容
-
如果装载因子到达阈值,需先扩容,插入数据,插入数据会变得很慢
-
可以采用渐进式的扩容
- 先申请新的空间,但是不立即迁移
- 每次迁移一点
-
查询时则从新散列表中查找,没有再去老的散列表中查找
\
如何选择冲突解决方法
| 开放寻址法 | 链表法 | |
|---|---|---|
| 优点 | 存储连续空间中,有效利用cpu缓存 | 空间利用率更高 |
| 缺点 | 删除数据需要特殊标记冲突代价更高 | 指针需要占据额外的存储空间不能利用CPU缓存 |
| 适用场景 | 适用于数据量小,装载因子(<1)小的时候 | 适合存储大对象、大数据量的散列表 比开放寻值法更灵活 |
工业散列表分析
-
以HashMap为例
- 初始化大小=16
- 装载因子=0.75
- 利用链表法解决散列冲突
- 散列函数 hashcode()
总结
-
工业级的散列表
-
支持快速地查询、插入、删除操作\
-
内存占用合理,不能浪费过多的内存空间\
-
性能稳定,极端情况下,散列表的性能也不会退化到无法接受的情况\
-
-
怎么设计
-
高效的散列函数 随机且均匀
-
设定装载因子,设计动态扩容策略
-
选择合适的散列冲突解决方法
- 开放地址法
- 链表法
-