设计一个可应对各种异常情况的工业级散列表

何为一个工业级的散列表?

1)支持快速的查询、插入、删除操作。

2)内存占用合理,不能浪费过多的内存空间。

3)性能稳定,极端情况下,散列表的性能也不会退化到无法接受的情况。

如何设计散列函数?

首先,散列函数的设计不能太复杂。过于太复杂的散列函数,势必会消耗很多计算时间,也就间接的影响到散列表的性能。其次,散列函数生成的值要尽可能随即并且均匀分布,这样才能避免或者最小化散列冲突,即使出现冲突,散列到每个槽里的数据也会比较平均,不会出现某个槽内数据特别多的情况。

实际工作中还要综合考虑各种因素,比如关键字的长度、分布、特点、散列表的大小……

1 数据分析法:分析数据结构,取比较随机的数据部分作为散列值。

2 直接寻址法:以数据元素关键字本身或它的线性函数作为散列函数。

3 平方取中法:先取关键字的平方,然后根据可使用空间的大小,选取平方数是中间几位为散列值。

4 折叠法:将关键字分割成位数相同的几部分,然后取这几部分地叠加和。

5 随机数法:步长采用随机函数计算得到。

装载因子过大了怎么办?

对散列表动态扩容,重新申请一个更大的散列表,将数据搬移到新散列表中。

装载因子的阈值需要选择得当。大了会导致冲突过多,小了会导致内存浪费严重。

要权衡时间、空间复杂度。如果内存空间不紧张,对执行效率要求很高,可以降低装载因子的阈值。如果内存紧张,对执行效率要求不高,可以增加装载因子的阈值。

如何避免低效地扩容?

为了解决一次性扩容耗时过多的情况,可以将扩容操作穿插在插入操作的过程中,分批完成。当装载因子到阈值之后,只申请新空间,但并不将老数据搬移到新散列表中。当有新数据要插入时,将新数据插入到新散列表中,并从老散列表中拿出一个数据放入到新散列表。

如何选择冲突解决方法?

1 开放寻址法

优点:散列表中的数组都存储在数组中,可以有效的利用CPU缓存加快查询速度。且序列化简单。

缺点:删除数据比较麻烦,需要特殊标记已经删除掉的数据。冲突代价更高。更浪费内存空间。

适合场景:数据量比较小,装载因子小。

2 链表法

优点:对内存地利用率高。对大装载因子地容忍度更高。

缺点:比较消耗内存。对CPU缓存不友好。

适合场景:大对象、大数据量

优化:将链表法中的链表改造为其他高效的动态数据结构,比如跳表、红黑树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值