📜  散列|设置 2(单独链接)

📅  最后修改于: 2021-10-27 07:37:18             🧑  作者: Mango

我们强烈建议参考下面的帖子作为先决条件。
散列|第一套(介绍)

什么是碰撞?
由于散列函数为一个大整数或字符串的键为我们提供了一个小数字,因此两个键可能会产生相同的值。新插入的键映射到哈希表中已经占用的槽的情况称为冲突,必须使用某种冲突处理技术来处理。

与大桌子碰撞的几率是多少?
即使我们有大表来存储密钥,也很可能发生冲突。一个重要的观察是生日悖论。只有 23 个人,两个人生日相同的概率是 50%。

如何处理碰撞?
处理碰撞的方法主要有两种:
1) 单独链接
2) 开放寻址
在本文中,仅讨论单独的链接。我们将在下一篇文章中讨论开放寻址。

分离链:
这个想法是让哈希表的每个单元格都指向一个具有相同哈希函数值的记录链表。

让我们考虑一个简单的哈希函数为“ key mod 7 ”,密钥序列为 50, 700, 76, 85, 92, 73, 101。

哈希链

用于链式散列的 C++ 程序

好处:
1) 实施简单。
2)哈希表永远不会填满,我们可以随时向链中添加更多元素。
3) 对散列函数或负载因子不太敏感。
4) 它主要用于不知道可以插入或删除多少键和多频繁键的情况。

缺点:
1)链接的缓存性能不好,因为键是使用链表存储的。开放寻址提供了更好的缓存性能,因为所有内容都存储在同一个表中。
2)空间浪费(哈希表的某些部分从未使用过)
3) 如果链变长,那么在最坏的情况下,搜索时间会变成 O(n)。
4) 为链接使用额外的空间。

链接性能:
可以在假设每个键同样可能被散列到表的任何插槽(简单的统一散列)的情况下评估散列的性能。

m = Number of slots in hash table
 n = Number of keys to be inserted in hash table
 
 Load factor α = n/m 
  
 Expected time to search = O(1 + α)
 
 Expected time to delete = O(1 + α)

Time to insert = O(1)

 Time complexity of search insert and delete is 
 O(1) if  α is O(1)

存储链的数据结构:

  • 链表
    • 搜索:O(l) 其中 l = 链表的长度
    • 删除:O(l)
    • 插入:O(l)
    • 缓存不友好
  • 动态大小的数组(向量C ++,ArrayList的在Java中,列表在Python)
    • 搜索:O(l) 其中 l = 数组长度
    • 删除:O(l)
    • 插入:O(l)
    • 缓存友好
  • 自平衡 BST(AVL 树,红黑树)
    • 搜索:O(log(l))
    • 删除:O(log(l))
    • 插入:O(l)
    • 缓存不友好
    • Java 8 以后将此用于 HashMap

下一篇:
冲突处理的开放寻址

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程