字符串hash的研究

字符串哈希的研究

关于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++;
}

附:hashSethashMap的哈希函数(以便比较)

private int SystemHash(String s) {
      int hash = s.hashCode();
      hash ^= (hash >>> 20) ^ (hash >>> 12);
      return (hash ^ (hash >>> 7) ^ (hash >>> 4));
}

 

 

必须说明:现在只测试英文单词为存入的数据对象。

分析:

    刚开始想到设计1是根据字符的二进制编码的。Javachar型数据是2 byte。但想到超过ASCLL256char型数据没法手工输入(我试了一下,char型数据超过256的都打印个?),最常用的英文单词实际上就是char数组,每个字母必不超过256。说了这么多,只想说明此时一个字母虽然是2 byte,但是变成二进制的话只有低8位存数据,高8位就都是 0 了。

OK,上面的前提是解释我的测试的铺垫。

 
    将上面的32位存储结构分为四份(即将一个int型数据88位的分为四份,并分别标号为1234)。

假如现在有一个数组a,数组存有5个元素,假设为12345,设计1的哈希过程是这样的:

 

 

最终插入12345完成!!!

    这个设计在存储数据少的时候还是比较让人满意的,但是,一看这个表格,顿时就惊呆了,这个表格说明了什么——加入hash表的长度为1000,那么取余后得到的索引位置只与存入的字符串的最后2个字母有关!!!那肯定是不行的,加入有abcdecbade存入,那肯定得撞车了。

    然后,稍微改进了一下,得到设计2

    同样的有:

嗯,现在好多了,34两个低位都与整个数组元素扯上了关系,当再加入abcdecbade后,再撞车已经几乎不可能发生了。

    现在想想,既然扯关系,那不如把关系扯得错综复杂一点,然后就得到设计3:把hash<<8改为hash<<7,即标号4的低位模块的数据没有全部移到标号3的模块,而是插一腿到原来自己呆的模块。此时,额,已经很难追寻踪迹了。。。

    那设计4怎么又加上hash<<24呢?很简单,就是让hash更复杂,但这个复杂是有道理的,目的就是让标号12的模块也与存入的整个字符串扯上关系(由表可见,标号1的模块只与少数字符数组关联),自此,便可大胆提出类似巴赫猜想的假设:如果字符数组的长度越长,那么设计4的散列效果肯定比较好。

下表为根据运行结果得到的统计数据:



 

现在只能看着数据发呆了,不管怎么说,还是能得到些信息的:

    1. 设计2和设计4的数据基本一样,也就是说hash<<8hash<<7是差不多的,hash<<7并不能增加散列效果;

    2. 在哈希表容量少、插入数组短的时候,自己的设计还是可以的,但是容量大、插入数据长的时候,那就比较劣了。

    3. hash<<24这一句并没有给设计4带来长数组的散列效果。(唉,有时候,猜想没有得到 验证也是很痛苦的)。

    4. 最重要的一点:我输了,彻底的输了,平均下来,系统的hash函数就远远抛下了我写的hash,特别是容量更大、数组长度更长的时候,差距就更明显了。

    不过,没有绝对好的hash,只有相对合适的hash

    探索路程,依然的,在路上……

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值