美文网首页
哈希(hash)(散列)算法

哈希(hash)(散列)算法

作者: 天探女 | 来源:发表于2020-02-29 09:06 被阅读0次

[toc]

散列算法

散列函数

正整数

将整数散列使用的方法是<font color="red">除留余数法</font>。

选择大小为<font color="red">素数</font>M的数组,对于任意正整数k,计算k除以M的余数,即k%M。可以有效的将键散列在0到M-1范围内

Java中Integer的hashCode函数默认返回int值本身

浮点数

如果键是0到1的实数,将他乘以M并<font color="red">四舍五入</font>得到一个0到M-1的索引值。但这个方法效果不好,键的高位对索引值影响大,最低位对散列结果没有影响。

更好的方法是将键表示为二进制数然后使用除留余数法。

字符串

可以使用除留余数法

int hash=0;
for(int i=0;i<s.length();i++)
    hash =  (R * hash + s.charAt(i)) % M;

其中java中String计算hashCode的方法

public int hashCode() {
    int h = hash; // hash默认=0,当String用new初始化的时候才会初始化成其他值
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

乘子为31的原因:

  1. 从注释中可知有如下式子(并没有什么乱用)
s_0\times31^{(n-1)} + s_1\times31^{(n-2)} + ... + s_{n-1}
  1. 31可以被jvm优化,首先可知java中利用移位运算符计算2幂乘数的乘除法效率高,由此可知

31 * i = ( i << 5 ) - i

31\times i=i \times 2^5 - i

(废话)

  1. 31是一个不大不小的质数,是优选质数之一,同理37、41、43亦是不错的候选质数。如果质数过小(如 2)会导致哈希值会挤在一个很小的范围内,冲突的概率会上升;如果质数过大(如 101)会导致哈希值过高很容易超过int的范围$\tt{ -2^{31} \rightarrow 2^{31}-1} $

    在《数据结构、算法与应用 C++语言描述》(第二版)中有一段与除留余数法$f(k)=k \bmod M$ 相关算子M的描述

    假设M是偶数。当k是偶数时,f(k)是偶数,当k是奇数时,f(k)是奇数。如果你的应用以偶数关键字为主,则大部分关键字都会映射到偶数为主的起始桶中,同理应用以奇数为主。所以M为偶数不能构建好的散列函数。同时,M不应该能被3、5、7等小奇数整除,也会产生不良的散列函数。故,应该选择既不是偶数又不会被小奇数整除的数,<font color='red'>理想的M应该是一个素数</font>,当你不能用心找到与散列表长度相近的素数,应该选择不能被2和19之间的数整除的M

参考链接:科普:为什么 String hashCode 方法选择数字31作为乘子

散列算法的步骤

根据散列函数构造哈希表

碰撞处理

拉链法(链表法)

链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位

/**
 * 在槽位bucketIndex新添加一个Entry
 * 
 * 先获取原来槽位的值(可能为null)
 * 创建一个新的Entry,并链上原来槽位的值,形成一个新的链表
 * 放入槽位,然后扩容
 * 
 * 查询到这个槽位的时候,必须要遍历链表才行,先插入的在链表后
 */
void addEntry(int hash, K key, V value, int bucketIndex) {  
    Entry<K,V> e = table[bucketIndex];  
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  
    if (size++ >= threshold)  
        resize(2 * table.length);  
}

线性探测法(开放地址法)

开放地址法是通过一个探测算法,当某个槽位已经被占据的情况下继续查找下一个可以使用的槽位

相关文章

  • 哈希算法

    什么是哈希算法 了解哈希算法需要了解以下几个概念。 散列表(hash table) 与散列函数 散列表也叫哈希表是...

  • python之哈希算法

    哈希(Hash)算法:`hash(object)` 一,基本概念 哈希算法将一个不定长的输入,通过散列函数变换成一...

  • 哈希算法

    哈希算法(Hash Algorithm)又称散列算法、散列函数、哈希函数,是一种从任何一种数据中创建小的数字“指纹...

  • 08 - Hash算法

    HASH算法简介 Hash:一般翻译做”散列“,也有直接音译为”哈希“,就是把任意长度的输入通过散列算法变成固定长...

  • 剖析HashMap(1.7)

    一、哈希? hash,散列,直译为哈希。哈希表,即为散列存储结构,给定一个key值,通过一定的哈希算法f(x),得...

  • Hash 算法

    散列算法(Hash Algorithm),又称哈希算法,杂凑算法,是从任意文件中创造小的数字[指纹]的方法。散列算...

  • Hash存储

    什么是哈希 哈希又称作散列(Hash ),就是讲任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列...

  • 小白入门——哈希算法

    哈希 哈希(Hash)也称为散列,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,这个输出值就是散列值。...

  • HashMap实现原理

    Hash算法 Hash,一般翻译做“散列”,也直接音译为“哈希”。就是把任意长度的输入通过散列算法,变换成固定长度...

  • 2.哈希加密 & base64加密

    一、哈希HASH 哈希(散列)函数MD5 SHA1/256/512 HMAC Hash的特点: 1.算法是公开...

网友评论

      本文标题:哈希(hash)(散列)算法

      本文链接:https://www.haomeiwen.com/subject/eglfqftx.html