散列法
散列法是一种搜索算法,它可以根据各元素的值来确定存储位置,然后将位置保管在散裂表中,从而实现数据的高速搜索.
高效的
- 插入
- 搜索
- 删除
数据结构
由容纳m个元素的数组T组成,理论上能够存储m个不同的元素,不过一般容量达到0.75m时,就会对数组进行扩容.因为此时hash函数的冲突概率会变大.
注意事项
- 哈希函数
- 哈希冲突的解决办法有多种,常见的有
- 开放地址法,双散列结构中使用的开放地址法.
- 链地址法
在双散列结构中一旦出现冲突 , 程序会调用第二个散列闲数来求散 列值 。
散列函数 有k和i两个参数.这里的i是发生冲突后计算下一个散列值的次数.只要散列函数起了冲突 , 就会依次调用,,,,...直到不发生冲突为止,然后返回这个h(k,i)的值作为散列值。
- 因为下标每次移动个位置,所以必须保证 T的 数组的长度m 与 互质,否则会出来无法生成下标的情况.
- 可以特意让m为质数,然后取一个小于m的值为,从而避免上述情况的发生.
题目
请实现一个能执行以下命令的简易 “ 字典 ” 。
- ► insert s t r : 向字典中添加字符串价
- ► find str : 当前字典中包含幻 〃 时输出 yes , 不包含时输出 no
5.4.hash.go 此处用法像set
package ch5
//insert str: 向字典中添加字符串str
//find str: 当前字典中是否包含str,包含返回true,不包含返回false
import (
"strings"
)
const M = uint64(1046527)
var H [M]string
func getChar(ch byte) uint64 {
switch ch {
case 'A':
return 1
case 'C':
return 2
case 'G':
return 3
case 'T':
return 4
}
return 0
}
func getKey(s string) uint64 {
sum := uint64(0)
p := uint64(1)
i := 0
for i = 0; i < len(s); i++ {
sum += p * getChar(s[i])
p *= 5
}
return sum
}
func h1(key uint64) uint64 {
return key % M
}
func h2(key uint64) uint64 {
return 1 + (key % (M - 1))
}
func find(s string) bool {
key := getKey(s)
i := uint64(0)
for i = 0; ; i++ {
h := (h1(key) + i*h2(key)) % M //此处可以将h1提到循环外,进行优化,为了方便理解没有提出
if strings.Compare(H[h], s) == 0 {
return true
} else if len(H[h]) == 0 {
return false
}
}
return false
}
//插入成功返回true
func insert(s string) bool {
key := getKey(s)
i := uint64(0)
for i = 0; ; i++ {
h := (h1(key) + i*h2(key)) % M //此处可以将h1提到循环外,进行优化,为了方便理解没有提出
if strings.Compare(H[h], s) == 0 {
return false
} else if len(H[h]) == 0 {
H[h] = s
return true
}
}
return false
}