面试题答案
一键面试开放地址法
- 策略:当发生哈希冲突时,通过探测哈希表中的其他空闲位置来存储新元素。常见的探测方式有线性探测(每次探测下一个相邻位置)、二次探测(探测距离按二次函数增长)和双重哈希(使用第二个哈希函数计算探测步长)。
- 性能影响:
- 读性能:由于可能需要多次探测才能找到目标元素,在冲突严重时,读操作的时间复杂度会从理想的O(1)上升,性能下降。
- 写性能:插入时若冲突频繁,寻找空闲位置会花费更多时间,影响写性能。而且随着哈希表装填因子增大,冲突概率增加,写操作时间复杂度上升。
- 扩展性:哈希表大小固定时,扩展性差。当元素数量接近哈希表容量时,冲突急剧增加,性能恶化。若要扩展哈希表,需要重新计算所有元素的哈希值并重新插入,开销巨大。
链地址法(拉链法)
- 策略:哈希表的每个槽位对应一个链表,发生哈希冲突时,将冲突的元素插入到对应槽位的链表中。如果链表过长,可以将链表转换为红黑树等平衡二叉树结构以提高查找效率。
- 性能影响:
- 读性能:理想情况下,每个链表长度较短,查找时间复杂度接近O(1)。但链表过长时,查找需要遍历链表,时间复杂度会变为O(n),性能下降。转换为红黑树后,查找时间复杂度稳定为O(log n),读性能提升。
- 写性能:插入操作只需在链表头部或尾部添加元素,平均时间复杂度为O(1),性能较好。但当链表转换为红黑树时,插入操作需要维护树的平衡,开销相对较大。
- 扩展性:扩展性较好,当元素数量增加导致冲突加剧时,可以通过增加哈希表的槽位数来分散元素,减少链表长度,提升性能。
再哈希法
- 策略:使用多个哈希函数对同一数据进行计算,当第一个哈希函数产生冲突时,尝试使用其他哈希函数计算新的哈希值,直到找到一个未冲突的位置。
- 性能影响:
- 读性能:每次读取都要计算多个哈希值,增加了计算开销。但如果哈希函数设计合理,能有效减少冲突,读性能仍可保持在较好水平。
- 写性能:写入时同样需要多次计算哈希值,开销较大。不过可以通过快速判断哈希值是否冲突,减少不必要的计算,在一定程度上维持写性能。
- 扩展性:扩展性相对较好,当数据量增加时,可以通过调整哈希函数的数量或参数来适应,减少冲突。但过多的哈希函数会增加计算资源消耗。
公共溢出区法
- 策略:另外开辟一个公共溢出区,专门存放哈希冲突的元素。当发生冲突时,将冲突元素存放在公共溢出区。
- 性能影响:
- 读性能:读操作时,首先在原哈希表查找,若未找到再到公共溢出区查找,增加了查找路径和时间,性能下降。
- 写性能:写操作时,若发生冲突直接写入公共溢出区,相对简单,但公共溢出区可能会成为性能瓶颈,随着溢出元素增多,性能变差。
- 扩展性:扩展性差,公共溢出区的大小难以预估,过小容易再次冲突,过大则浪费空间。当数据量持续增加,公共溢出区性能问题会愈发严重。