字符串哈希的研究
关于hash函数,其存在的理由就是让存入的数据得到好的立足之地(就像给存入的数据一个唯一的门牌号,我们就可以很容易的找到它所在地点),而且不让数据扎堆也是很重要的(而不是让数据扎堆,毕竟在一间几十上百号人的屋子找个人相对比较困难的)。
由此,hash函数应该,也必须要让数据“散开”,数据不必争房子住,如此冲突就少了,社会也就和谐了。
以下为hash设计历程:(一步一步、做足苦力啊!先贴代码,然后是自己的一点分析,再后是测试的统计数据)
设计1:
private int FirstHash(String str){
char[] chars = str.trim().toCharArray();
int hash = 0;
int count = 0;
int length = chars.length;
while (count < length) {
hash = (int) chars[count] + (hash << 8) + (hash << 16);
count++;
}
return hash & 0x7FFFFFFF;
}
设计2:
while (count < length) {
hash = (int) chars[count] + (hash << 8) + (hash << 16) – hash;
count++;
}
设计3:(只改动了一个数据哦!!!)
while (count < length) {
hash = (int) chars[count] + (hash << 7) + (hash << 16) – hash;
count++;
}
设计4:
while (count < length) {
hash = (int) chars[count] + (hash << 7) + (hash << 16) + (hash << 24) – hash;
count++;
}
附:hashSet、hashMap的哈希函数(以便比较)
private int SystemHash(String s) {
int hash = s.hashCode();
hash ^= (hash >>> 20) ^ (hash >>> 12);
return (hash ^ (hash >>> 7) ^ (hash >>> 4));
}
必须说明:现在只测试“英文单词”为存入的数据对象。
分析:
刚开始想到设计1是根据字符的二进制编码的。Java中char型数据是2 byte。但想到超过ASCLL值256的char型数据没法手工输入(我试了一下,char型数据超过256的都打印个“?”),最常用的英文单词实际上就是char数组,每个字母必不超过256。说了这么多,只想说明此时一个字母虽然是2 byte,但是变成二进制的话只有低8位存数据,高8位就都是 0 了。
OK,上面的前提是解释我的测试的铺垫。

将上面的32位存储结构分为四份(即将一个int型数据8位8位的分为四份,并分别标号为1、2、3、4)。
假如现在有一个数组a,数组存有5个元素,假设为“12345”,设计1的哈希过程是这样的:

最终插入“12345”完成!!!
这个设计在存储数据少的时候还是比较让人满意的,但是,一看这个表格,顿时就惊呆了,这个表格说明了什么——加入hash表的长度为1000,那么取余后得到的索引位置只与存入的字符串的最后2个字母有关!!!那肯定是不行的,加入有“abcde”和“cbade”存入,那肯定得撞车了。
然后,稍微改进了一下,得到设计2:
同样的有:

嗯,现在好多了,3、4两个低位都与整个数组元素扯上了关系,当再加入“abcde”和“cbade”后,再撞车已经几乎不可能发生了。
现在想想,既然扯关系,那不如把关系扯得错综复杂一点,然后就得到设计3:把“hash<<8”改为“hash<<7”,即标号4的低位模块的数据没有全部移到标号3的模块,而是插一腿到原来自己呆的模块。此时,额,已经很难追寻踪迹了。。。
那设计4怎么又加上“hash<<24”呢?很简单,就是让hash更复杂,但这个复杂是有道理的,目的就是让标号1和2的模块也与存入的整个字符串扯上关系(由表可见,标号1的模块只与少数字符数组关联),自此,便可大胆提出类似巴赫猜想的假设:如果字符数组的长度越长,那么设计4的散列效果肯定比较好。
下表为根据运行结果得到的统计数据:

现在只能看着数据发呆了,不管怎么说,还是能得到些信息的:
1. 设计2和设计4的数据基本一样,也就是说“hash<<8”和“hash<<7”是差不多的,“hash<<7”并不能增加散列效果;
2. 在哈希表容量少、插入数组短的时候,自己的设计还是可以的,但是容量大、插入数据长的时候,那就比较劣了。
3. “hash<<24”这一句并没有给设计4带来长数组的散列效果。(唉,有时候,猜想没有得到 验证也是很痛苦的)。
4. 最重要的一点:我输了,彻底的输了,平均下来,系统的hash函数就远远抛下了我写的hash,特别是容量更大、数组长度更长的时候,差距就更明显了。
不过,没有绝对好的hash,只有相对合适的hash。
探索路程,依然的,在路上……

- 大小: 2.9 KB

- 大小: 11.7 KB

- 大小: 7.1 KB

- 大小: 6.9 KB
分享到:
相关推荐
“javascript字符串hash”指的是在JavaScript中,将字符串转化为一个固定长度的数字表示,常用于数据校验、唯一标识或简化的比较操作。常见的JavaScript字符串hash算法有MD5、SHA系列等,也可以自定义简单算法,如将...
在提供的压缩包文件"C#字符串加密解密"中,可能包含了关于这些加密解密方法的源代码示例,你可以下载并研究其中的实现细节,以便在自己的项目中灵活运用。记住,理解并正确使用这些工具对于确保应用程序的数据安全性...
这段代码首先导入了Python的hashlib库,然后定义了一个函数`sha1_hash_string`,它接受一个字符串,将其编码为UTF-8,然后使用`sha1`方法生成哈希值,并返回16进制表示的哈希。最后,它打印出"Hello, World!"这个...
这个库,名为"用于将字符串编码成Base16Base32Base64MD5SHA1的库",提供了对几种常见编码格式和哈希函数的支持,包括Base16、Base32、Base64,以及MD5和SHA-1。这些工具在JavaScript环境中尤其有用,因为它们可以...
在Java编程语言中,字符串(String)、Hashtable、Vector以及接口(interface)都是基础且重要的概念。在这个小练习中,我们分别看到了它们的使用。 首先,我们来看字符串(String)的运用。在Java中,字符串是不可变的...
了解了C#中MD5摘要串转换为二进制字符串的方法后,如果对加密解密有更深入的兴趣,可以研究C#中其他相关的加密算法,如AES、DES、RSA等。同时,熟悉C#中线程、文件操作、窗体控制、数据结构和算法等方面的知识,对于...
通过研究这个压缩包,开发者可以学习到如何在实际项目中实施字符串加密解密,提高数据安全性,并了解当前最佳的加密实践。同时,这也是一个很好的机会去熟悉和掌握PHP的加密相关函数和库,这对于任何涉及用户数据...
GeoHash算法则是一种地理位置编码技术,可以将一个地理位置编码为一个较短的字符串。它将地球表面划分为网格状,每个网格对应一个字符串。在共享单车动态回收点设置的研究中,GeoHash算法可以用来对骑行数据进行地理...
对于字符串加密,可以直接将字符串的字节序列作为输入数据。而对于文件加密,需要读取文件内容,将其按块处理。在VC6.0环境下,可以使用标准I/O库或文件流来读取文件,然后调用哈希函数的接口进行加密。 在实现过程...
HASH函数将一个字符串转换为固定长度的数值,相同的字符串会产生相同的HASH值,不同字符串则有非常小的概率产生相同的HASH。在PE分析中,可以使用HASH值快速检查函数名是否存在或匹配,而无需完全比较整个字符串。 ...
**Rabin哈希函数**,也称为Rabin的随机多项式摘要算法,是一种在计算机科学领域,特别是数据完整性检查和文件校验中广泛...同时,对于研究和开发新的字符串处理算法或安全协议的人员来说,这也是一个重要的基础知识。
SHA1(Secure Hash Algorithm 1)同样是哈希函数,输出长度为160位,以16进制表示为40位字符串。虽然比 MD5 更安全,但也存在碰撞问题,已被建议替换为更安全的 SHA-2 家族算法。 Base64 是一种用于将二进制数据...
在提供的代码片段中,我们看到一个名为`getHash`的函数,其接受两个参数:`b`(一个整数)和`i`(一个字符串)。该函数的主要逻辑如下: 1. **初始化数组**:首先创建两个数组`a`和`j`。`a`用于存储字符串`i`的字符...
- **字符串处理技巧**:如字符串长度的获取、字符数组的遍历等,是实现哈希函数的关键步骤。 综上所述,该哈希算法实现不仅展示了内联汇编的运用技巧,同时也提供了对哈希算法设计和实现的深刻洞察,对于计算机科学...
GEOHash是将地理位置信息编码为字符串的一种方法,它能够将二维地理坐标(经度和纬度)映射成一维字符串,并且按照一定的规则具有前缀和可分级的特性。这意味着越是接近的地理位置,它们的GEOHash编码前缀也越相似。...
在源码中,我们可以找到将经纬度转换为Geohash字符串的函数,以及反过来将Geohash字符串解析回经纬度的函数。编码过程通常涉及对坐标进行预处理、二进制编码、Base32转换,而解码则需要逆向执行这些步骤。 5. 空间...