数据结构与算法(20)——散列

  • 散列Hashing

散列是一种数据结构。由数据项的值来确定存放的位置。

散列表(哈希表)是一种数据集。散列的每一个存储位置称为一个槽,可用于存储数据,每个槽拥有唯一的名称。

 

 散列函数:最简单的求余:h(item) = item % 11

按照散列函数h(item)为每个数据项计算存放的位置后,就可以把数据项存入到相应的槽中。

 

将数据项如6个数据项插入后,占据了散列表的11个槽中的6个。槽被数据项占据的比例称为散列的“负载因子”,这里为6/11.

但当77和44这样的数除以11都余0时,那么77和44的存储位置则会冲突,因此需要一个完美的散列函数来解决这种哈希冲突

  • 完美散列函数

给定一组数据项,如果一个散列函数能把每个数据项映射到不同的槽中,那么这个散列函数就可以称为“完美散列函数”。对于一组固定数据,总是能想办法设计除完美散列函数。但如果数据项经常性的变动,很难有一个系统性的方法来设计对应的完美散列函数。当然冲突也不是致命性的错误,我们会有办法处理的。

    获得完美散列函数的一种方法是扩大散列表的容量,大到所有可能出现的数据项都能够占据不同的槽。(用空间换时间)但这种方法对数据项范围过大的情况并不适用,例如保存手机号11位数字,那完美散列函数要求散列表具有百亿个槽!!!会浪费太多存储空间。

    所以好的散列函数需要具备如下特性:冲突最少、计算难度低、节约空间。

    由于完美散列函数能够对任意不同的数据生成不同的散列值(长度固定),如果把散列值当作数据的“指纹”,要求具有唯一性,这种特性被广泛应用在数据的一致性校验上。

  • 散列函数设计

1.折叠法:将数据项按照位数分为若干段, 再将几段数字相加, 最后对散列表大小求余,得到散列值 。例如,对电话号码62767255 可以两位两位分为4段(62、76、72、55) 相加(62+76+72+55=265) 散列表包括11个槽,那么就是265%11=1 所以h(62767255)=1

2.折叠法+隔数反转法:比如(62、76、72、55)隔数反转为(62、67 、72、55) 再累加(62+67+72+55=256) 对11求余(256%11=3),所以h'(62767255)=3 

3.平方取中法:平方取中法,首先将数据项做平方运算, 然后取平方数的中间两位,再对散列表的 大小求余 。

4.编码:对于非数字可用ASCII编码。

  • 散列冲突的解决方案

1.线性探测:再找一个开放的空槽

 

 

2.再散列rehashing

 

 

3.数据链chaining:将容纳单个数据 项的槽扩展为容纳数据项集合

 

 

 

posted @ 2020-07-23 22:01  Yelush  阅读(611)  评论(0编辑  收藏  举报