数据结构与算法之美——散列表——实战篇(上)
一、前言 通过理论篇,我们知道,散列表的 查询效率 跟 散列函数、装载因子、散列冲突 等都有关系。如果散列函数设计得不好,或者装载因此过高,都可能导致散列冲突发生的概率升高,查询效率下降。 在极端情况下,有些恶意的攻击者,还有可能通过精心构造的数据,使得所有的数据经过散列函数之后,都散列到同一个槽里。如果我们使用的是基于链表的冲突解决方法,那 这个时候,散列表就会退化为链表 ,查询的时间复杂度从O(1)退化为O(n)。 如果散列表中有10万个数据,退化后的散列表查询的效率就下降了10万倍。如何之前运行100次查询只需要0.1秒,那现在就需要1万秒。这样就有可能因为查询操作消耗大量CPU或者线程资源,导致系统无法响应其他请求,从而达到拒绝服务攻击(Dos)的目的。 如何设计一个可以应对各种异常情况的工业级散列表,来 避免在散列冲突的情况下,散列表性能的急剧下降,并且能抵抗散列碰撞攻击 ? 二、如何设计散列函数 散列函数设计的好坏,决定了散列表冲突的概率大小,也直接决定了散列表的性能,那什么才是好的散列函数呢? 1、散列函数的设计不能太复杂 2、散列函数生成的值要尽可能随机并且均匀分布 三、装载因子过大怎么办 提及散列表的装载因子的时候说过,装载因子越大,说明散列表中的元素越多,空闲位置越少,散列冲突的概率就越大。不仅插入数据的过程要多次寻址或者拉很长的链,查找的过程也会因此变得很慢。