面试_java_散列表

87 阅读2分钟

散列表(哈希表)是一个具有固定大小的数组,它能够 以常数时间执行插入,删除和查找操作。数组中的每个节点都存着一个key-value整体,他俩不是分开存的。


散列函数(哈希函数)就是确定元素在数组中位置的规则(将key转化为数组下标)。当不同元素被分配到同一位置,就是发生了冲突(碰撞)。


解决散列冲突通常有两种方法:开放地址法、拉链法



开放定址法

位置开放,如果冲突发生,就按照某策略选择另外一个可用的位置(策略:线性探测、平方探测)

优点

  • 数据存储在数组中,地址连续,对CPU友好
  • 不需要额外空间

缺点

  • 数组长度在一开始就确定,无法扩增
  • 所有数据存储在一个数组中,有可能会出现连续冲突



拉链法

简单来说,就是在每个数组元素上都加一个链表结构,经过哈希函数得到数组下标后,若没有冲突,放到下标位置成为链表的首结点,若发生冲突,就追加到下标位置挂载的链表中。

优点

  • 链表上的结点空间是动态申请的,更适合于预先无法确定表长的情况;

  • 每个元素最多冲突一次

缺点

  • 结点零散分布在内存中,不连续,对CPU缓存不友好

  • 需要额外的空间来保存指针




选择

当数据量比较小,适合采用开放寻址法。反之用拉链法。另外,比起开放寻址法,拉链法更加灵活,支持更多的优化策略,比如在HashMap中用红黑树代替链表。