Jenkins hash

最早,Bob Jenkins提出了多个基于字符串通用Hash算法(搜Jenkins Hash就知道了),而Thomas Wang在Jenkins的基础上,针对固定整数输入做了相应的Hash算法。其64位版本的 Hash算法如下:
uint64_t hash(uint64_t key) {
  key = (~key) + (key << 21); // key = (key << 21) - key - 1;
  key = key ^ (key >> 24);
  key = (key + (key << 3)) + (key << 8); // key * 265
  key = key ^ (key >> 14);
  key = (key + (key << 2)) + (key << 4); // key * 21
  key = key ^ (key >> 28);
  key = key + (key << 31);
  return key;
}

其关键特性是:
1.雪崩性(更改输入参数的任何一位,就将引起输出有一半以上的位发生变化)
2.可逆性

逆Hash函数为:
uint64_t inverse_hash(uint64_t key) {
  uint64_t tmp;

  // Invert key = key + (key << 31)
  tmp = key-(key<<31);
  key = key-(tmp<<31);

  // Invert key = key ^ (key >> 28)
  tmp = key^key>>28;
  key = key^tmp>>28;

  // Invert key *= 21
  key *= 14933078535860113213u;

  // Invert key = key ^ (key >> 14)
  tmp = key^key>>14;
  tmp = key^tmp>>14;
  tmp = key^tmp>>14;
  key = key^tmp>>14;

  // Invert key *= 265
  key *= 15244667743933553977u;

  // Invert key = key ^ (key >> 24)
  tmp = key^key>>24;
  key = key^tmp>>24;

  // Invert key = (~key) + (key << 21)
  tmp = ~key;
  tmp = ~(key-(tmp<<21));
  tmp = ~(key-(tmp<<21));
  key = ~(key-(tmp<<21));

  return key;
}
由上述的算法实现可知,原始的hash算法过程是非常快的,而其逆Hash算法则比较慢一些。

特征:0.

参考:
1.jenkins 32位Hash算法: http://burtleburtle.net/bob/hash/integer.html
2. Geoffrey Irving's blog:  http://naml.us/blog/tag/thomas-wang

Jenkins Hash 是由 Bob Jenkins 设计的一种哈希算法,它可以将任意长度的输入数据映射为一个 32 位的哈希值。Jenkins Hash 的实现非常简单,具有良好的散列性和高效性,被广泛应用于各种编程语言中。 Jenkins Hash 的核心思想是将输入数据分成若干个 4 字节的块,对每个块进行一系列简单的位运算和乘法运算,最后将结果累加起来得到哈希值。具体来说,Jenkins Hash 的伪代码如下: ``` uint32_t jenkins_hash(const void* key, size_t length, uint32_t initval) { uint32_t a, b, c, len; const uint8_t* data = (const uint8_t*)key; len = length; a = b = 0x9e3779b9; c = initval; while (len >= 12) { a += (data[0] + ((uint32_t)data[1] << 8) + ((uint32_t)data[2] << 16) + ((uint32_t)data[3] << 24)); b += (data[4] + ((uint32_t)data[5] << 8) + ((uint32_t)data[6] << 16) + ((uint32_t)data[7] << 24)); c += (data[8] + ((uint32_t)data[9] << 8) + ((uint32_t)data[10] << 16) + ((uint32_t)data[11] << 24)); a -= b; a -= c; a ^= (c >> 13); b -= c; b -= a; b ^= (a << 8); c -= a; c -= b; c ^= (b >> 13); data += 12; len -= 12; } c += length; switch (len) { case 11: c += ((uint32_t)data[10] << 24); case 10: c += ((uint32_t)data[9] << 16); case 9: c += ((uint32_t)data[8] << 8); case 8: b += ((uint32_t)data[7] << 24); case 7: b += ((uint32_t)data[6] << 16); case 6: b += ((uint32_t)data[5] << 8); case 5: b += data[4]; case 4: a += ((uint32_t)data[3] << 24); case 3: a += ((uint32_t)data[2] << 16); case 2: a += ((uint32_t)data[1] << 8); case 1: a += data[0]; } a -= b; a -= c; a ^= (c >> 13); b -= c; b -= a; b ^= (a << 8); c -= a; c -= b; c ^= (b >> 13); return c; } ``` 其中,`key` 是输入数据的指针,`length` 是输入数据的长度,`initval` 是初始哈希值。该函数使用三个 32 位的变量 `a`、`b` 和 `c` 来分别保存计算过程中的中间值,使用 `len` 来追踪剩余的数据长度,使用 `data` 来追踪当前处理的输入数据指针。最后,将 `c` 作为哈希值返回。 Jenkins Hash 的优点有: - 易于实现和快速计算。 - 具有良好的散列性能,能够避免哈希冲突,并产生良好的哈希分布。 - 支持增量哈希计算,可以在处理大型数据流时有效地避免内存问题。 由于 Jenkins Hash 的实现简单且性能优秀,因此它被广泛用于各种哈希表、数据结构、散列算法等场合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值