本篇博客主要记录了 字符串hash 的相关算法,包括:
1. 字符串hash初步
2. 字符串hash进阶(还不一定什么时候写,初步的内容在大部分情况下是够用的)
概述
散列(hash)是一种常用的算法思想,是一种典型的以空间换时间的做法。
对于整数型的散列算法在一般的数据结构课程或书籍中都会教授,这两个名词不知道是否会激起您的一些记忆:散列函数、冲突。
这篇博客不讨论散列函数的构造和冲突的解决办法,主要记录的是字符串的散列算法。字符串hash是指将一个字符串S映射为一个整数,使得这个整数可以尽可能的唯一表示S。
字符串hash初步
字符串hash初步是讨论如何用一个整数唯一的表示一个字符串的问题。
首先来看这么一个问题:如何将一个二维整点坐标P(x,y)用一个整数唯一的表示?(其中0≤x,y≤range)
很容易想到的是 整数=x*range+y。
回到字符串hash初步讨论的问题上,想想它的解决方案:
我们不妨设字符串S由A~Z这26个大写字母组成,再不妨把A~Z映射为0~25,这样就可以把26个字母对应到二十六进制中。
接着,按照二十六进制转换成十进制的方法,即可将这个S转换成一个十进制的数。由进制转换的结论可以知道,这个十进制的数是唯一的,于是上述问题得到解决,下面是实现:
int hashStr(char s[], int len){ //len:字符串的长度
int id = 0;
for(int i = 0; i < len; i++){
id = id*26 + (s[i]-'A');
}
return id;
}
如果字符串中加入了小写字母(a~z)呢?
和上面一样,只需要将a~z映射成26~51即可,实现方法也是类似的。
对于字符串中还包含数字的情况,有两种处理办法:
1. 同小写字符的处理办法一样,将数字映射到52~61,即增加到了62进制
2. 如果确保末尾是确定个数的数字,直接将整数数位“接上”即可。比如“BCD4”:按照前面的方法,”BCD”转换成整数为731,那么“BCD4”表示为7314。即731*10+4。下面是这个例子的实现:
int hashStr(char s[], int len){
int id = 0;
for(int i = 0; i < len-1; i++){
id = id*26 + (s[i]-'A');
}
id = id*10 + (s[len-1]-'0');
return id;
}
参考资料
胡凡. 算法笔记[M]. 机械工业出版社, 2016. 106-111