哈希(散列)
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构(用于存储关键字和及其关联的值)。
是关联数组抽象数据结构的一种实现
散列表的删除操作
- 删除一条记录一定不能影响后面的检索.
- 不能让散列表中的记录由于删除而不可用,释放的槽 应该能够 为将来的插入使用.
通过在被删除记录的位置上放一个特殊标记,这两个问题都可以解决,这个标记称为墓碑(tombstone).
墓碑将不会停止检索过程,但是标记的槽可在以后的插入所使用.
不幸地,墓碑增加了一些记录本身到其基位置地平均长度,超过了在墓碑不存在地情况下它所处的位置.
解决办法:
- 根据删除进行一次局部重组试图缩小平均路径长度.
- 定期重新对表进行散列(把最频繁访问的记录放到它们的基位置.
如何解决冲突问题:
寻找一个替代位置的过程称为冲突解决策略
冲图解决策略:
- 每个记录i有一个基位置 ---- h(ki) 得到
- 如果另一个记录占据了记录i的基位置,那么需要找到其他位置(空槽)来存储记录i
- 新槽由冲突解决策略决定
- 检索页遵循同样的策略来找出那些不在他们的基位置的记录
两种实现方法
- 开散列方法----拉链法:
把冲突记录存储在散列表外面 - 闭散列方法
把冲突记录存储在散列表另一个槽内
单链法实现方法:
把散列表中的每一个槽定义为一个链表的表头
数组加链表实现:
左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。
我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。
桶式散列实现方法:
桶式散列(Bucket Hashing)把散列表中的槽分成多个
桶bucket), 包含一个溢出桶(overflow bucket)
散列函数把每条记录分配到某个桶的第一个槽中。如果这个槽已经被占用,那么就把这条记录在桶中向下移,直到找到一个空槽。如果一个桶中被完全占满,那么就把这条记录存储在表的溢出桶中.
当检索记录时,首先检查合适的桶,然后检查溢出桶.
桶式散列的特点
桶式散列适用于实现基于磁盘中的散列表
因为桶的大小可以设置为磁盘块的大小。每当进行检索或者插入的时候,就把整个桶读入存储器。对于插入或者检索的所有处理都在这一次磁盘访问中,除非桶已经满了。如果桶已经满了,还要从磁盘中读出溢出桶。
自然,应当使溢出很小,从而使不必要的磁盘访问最少。