算法笔记(8)哈希

在M个数中查找某个数是否出现过,或者在一篇文章中查找一个单词是否出现过,又或者需要统计一篇文章中某个单词出现的次数,最直接的思维就是依据这个单词遍历整篇文章。显然,这种算法的时间复杂度随着文章篇幅的增多时间逐渐增加,那么如何写出一个常数级的查找算法呢?

哈希帮我们解决了这类问题。

简单的,对于整数查找,我们可以利用bool数组以空间换时间的方式,统计次数则换用int类型即可。那么,问题来了。对于过大的整数,单纯靠消耗空间显得极不明智。所以我们采取了散列函数,将一个较大的整数浓缩为一个唯一的小整数(即H(key))。这里对于整数哈希有几种常见方法。

1.直接定址法

最常见最实用的方法,即H(key)=key或H(key)=a*key+b

2.平方取中法

H(key)为key2的中间若干位,很少用。

3.除留取余法

即将key除以一个数mod得到的余数作为哈希的方法。显然,这样可以把一个很大的数转换为不超过mod的整数,从而缩小了范围。mod一般取素数便于覆盖范围内每一个数。

显然,我们在使用这些方法的某些时不能保证H(key)相同的两个key一定相等。我们又采取了一些方法来避免冲突。

1.线性探查法

当得到某个key的H(key)时,发现下标为H(key)的位置已被占领,那我们必须寻找新的hash,我们开始检查当前的下一位,即H(key)+1,如果也被占据,则以此类推,直到找到空闲位置为止,当我们到表末尾时,则返回表头继续检查即可。

2.平方探查法

为了避免线性探查扎堆的现象,我们采用H(key)+12,H(key)-12,H(key)+22,H(key)-22的方式检查,如果检查过程中,H(key)+k2超过表长,则对表长取模,如果H(key)-k2小于0,则不断加表长直到其大于0为止,如果想要避免负数带来的麻烦,则可以只进行正向探查。

3.链地址法

前两种由于指定了新的hash,所以称为开放定址法。这一种则将H(key)相同的所有key连接成单链表,并将多条这样的链表放入一个数组,使得数组arr[H(key)]=list(key),这样可以方便地查找H(key)的所有key值。

一般的,我们也会对字符或者字符串进行哈希。即将任意一个元素转换为唯一对应的整数,

对字符的哈希显然可以利用ASCII码,相比整数哈希更加简单。

对于字符串,我们要考虑字符串中的字符种类,对于一串大写字母字符串而言,一共26种字符,任意多个字符以任意方式组合,如果采用26进制 ,则每个字符串产生一个26进制数,如果将这个26进制数转换为10进制,即为H(key)。同理,对其他字符类型组合也一样。当初步得到唯一整数时,我们也可采用整数哈希来缩小整数范围。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章