`
totoxian
  • 浏览: 1034387 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

glibc的字符串哈希算法

 
阅读更多

glibc中对于字符串的哈希实现的比较好,首先看一下这个算法的实现函数:

static inline unsigned long int hash_string(const char *str_param)

{

unsigned long int hval, g;

const char *str = str_param;

hval = 0;

while (*str != '/0')

{

hval

hval += (unsigned long int) *str++; //新数据叠加到老数据上

g = hval & ((unsigned long int) 0xf

if (g != 0)

{

hval ^= g >> (HASHWORDBITS - 8); //将高4位和第一个字节的高4位按位异或

hval ^= g; //新数据的高4位清零,以提高下个循环中的右移效率

}

}

return hval;

}

这个哈希算法相当于一个轮转的算法,按照字符串的从左到右的顺序进行轮转异或,实际上类似于一个回滚加法,就是说一旦左边溢出,那么溢出数据将叠加到最右边,TCP/IP的校验码就是回滚加法计算得到的,这个加法很快很简单,然而这里的哈希算法并不是简单的将一个位回滚到开始的第一个位的位置,而是一共4个位一起回滚到了低字节的高4位,这样的好处就是既使得溢出的字节不丢失,将之异或到低位的某处,又不至于一个位一个位的溢出时效率那么低下,同时又不将它回滚到低4位,而是低8位的高4位,这样能充分降低溢出数据的权值,注意这是在哈希而不是在计算校验值,如果将来取模的话,越是低位的数据影响越大,因此此算法确实是按照按照字符串从左到右的顺序权值依次降低的方式进行扫描和计算的,结论就是字符串后面的字符会比较大的影响哈希结果。对于每一个字符加到已有结果上的时候,必须保证此次循环中这个加上去的新值没有被原来的数据“污染”,因此才会回滚到低8位的高4位。看看hash_string在什么时候使用:

nls_uint32 hash_val = hash_string(const char * str_param, size_t len) (msgid);

nls_uint32 idx = hash_val % domain->hash_size;

nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));

果然最终要取模。

哈希算法有两个重要的指标,这就是效率和分布概率,效率当然越高越好,算法越快越好,而分布性当然是分布越均匀越好,times33算法应该是很经典的一个算法了,这个算法很简单,简单意味着效率会很高,起码不会太低,因为没有什么额外的约束需要维护,算法的额外成本几乎为零,那么分布性呢,这就要实践出真知了,一般的观点,一个字符串的哈希就是将所有的字符叠加,但是那太容易碰撞,要知道最终的和越大,碰撞的可能就越大,因为给出一个值,要用加法得到这个值的可能性太多了,给出的数值越大可能性就越多,因此不可取,那么乘法呢?和加法一样,但是比加法要好,主要受到奇数偶数以及质数的限制,因此不能采用连乘的方式,而应该用固定乘数的方式,乘数不能固定乘偶数,因为那样的话,最终的积会有太多的可能性通过乘法得到,要使最终的积不太可能有太多的因数起码要用奇数,现在考虑用什么奇数比较好,当然是因数越少越好了,15,17,31,33,63,65,127,129这些都是奇数,看得出这些数字都是围绕在2的整数次方周围的数字,选这几个数字的好处在于乘法可以归结为一个移位操作和一个加法或者减法操作,效率很高,我们需要结果最好因数越少越好,那么最好的就是质数了,可是这里却不能选择质数,看看这是为什么?因为还要加上一个*str,如果本来就是质数,由于质数本来就少,那么加上随便一个数都可能导致结果不再是质数,而如果本来不是质数,那么加上一个数值后虽然也是很大的概率不是质数,但是还是有那么一点可能是质数的,概率要比前者大一些,这只是一个统计意义上的论述,最终的结果不一定必须是质数,只要保证因数尽可能少就是了,因此实际上不一定是33,129也可以的。最后看一下times33算法的实现:

unsigned int Hash(char *str)

{

unsigned int hash = 5381;

while (*str)

{

hash += (hash

}

return (hash & 0x7FFFFFFF);

}

分享到:
评论

相关推荐

    glibc2.8 glibc2.5glibc2.3

    glibc2.8 glibc2.5glibc2.3

    ryu:将浮点数转换为十进制字符串

    在撰写本文时,这些是已知最快的浮点到字符串转换算法。 固定的科学转换例程比sprintf的常规实现快几倍(我们将其与glibc,Apple的libc,MSVC等相比)。 通过转换为64位,然后使用64位例程,可以实现为16位和32位...

    glibc-2.14.1所有的rpm包

    glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。linux的glibc包升级需将所有的glibc相关的包都进行升级,否则影响linux大部分命令的使用。该资源包含如下...

    glibc-2.14.1 全套rpm包(CentOS6)

    CentOS6.X升级glibc-2.14全套rpm包,安装后glibc由2.12升级到2.14 $ strings /lib64/libc.so.6 | grep GLIBC GLIBC_2.2.5 GLIBC_2.2.6 GLIBC_2.3 GLIBC_2.3.2 GLIBC_2.3.3 GLIBC_2.3.4 GLIBC_2.4 GLIBC_2.5 GLIBC_...

    glibc-2.28.tar.gz.7z

    glibc

    glibc-2.17 arm版本

    glibc-arm-2.17,glibc的arm版本,交叉编译gcc需要用到,截止目前为glibc的最新版本

    glibc rpm升级包

    linux glibc (2.14/2.15/2.18)rpm升级包

    cpp binutils gcc glibc-devel glibc-headers glibc-kernheade kernel-headersrs

    cpp binutils gcc glibc-devel glibc-headers glibc-kernheade kernel-headersrs包

    qt 安装缺少包 version“Glibc_2.9” not fount

    (1)以glibc-2.9.tar.gz为例; tar –zxvf glibc-2.4.tar.gz; (2) ./configure也就是说不能直接在在glibc-2.9这个目录中进行./configure,必须重新建立一个目录后并且进入后再在刚才的目录下进行./configure,例如就是...

    glibc-2.14.zip

    centos升级glibc 到glibc_2.14,rpm包,省去各种麻烦 strings /lib64/libc.so.6 | grep GLIBC

    glibc2.14.zip

    本文件用于linux服务器升级glibc2.14版本,具体操作可看博主博客的操作介绍,搜索“glibc”即可。

    glibc2.14.1 rpm安装包

    glibc2.14.1 rpm安装包,无需编译,直接rpm -ivh 进行安装,方便简单

    glibc2.14 .rar

    使用以下命令升级glibc rpm -Uvh glibc-utils-2.14.1-6.x86_64.rpm --nodeps rpm -Uvh glibc-2.14.1-6.x86_64.rpm --nodeps rpm -Uvh glibc-devel-2.14.1-6.x86_64.rpm --nodeps rpm -Uvh glibc-static-2.14.1-6....

    glibc 2.17rpm安装包及脚本

    glibc 2.17rpm

    glibc升级包 rpm 2.22

    该资源为升级glibc库的rpm包,版本是2.22,可以将glibc更新到GLIBC_2.23, 由于官网下载较慢,所以特此提供快速下载

    glibc-2.11.1.tar.gz

    glibc-2.11下载 项目在高版本linux版本编译,可执行文件放在低版本的服务器上跑,报错 undefined reference to `__isoc99_sscanf' 原因是我们的程序中使用的某个库,如xxx.a, xxx.so是在高版本的glibc环境里面...

    glibc2.14 rpm包

    升级glibc2.12到2.14,使用rpm -Uvh安装这6个包就可以

    glibc 2.14 rpm 安装包及安装命令

    glibc 2.14 rpm 安装包及安装命令

    glibc-2.0.1源码

    glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于 ...

    glibc-2.17-all-rpm.7z

    glibc-2.17安装所需全套rpm文件【本人亲测】: glibc-2.17-55.el6.x86_64.rpm glibc-common-2.17-55.el6.x86_64.rpm glibc-devel-2.17-55.el6.x86_64.rpm glibc-headers-2.17-55.el6.x86_64.rpm glibc-static-2.17-...

Global site tag (gtag.js) - Google Analytics