美文网首页
11.哈希表

11.哈希表

作者: LucXion | 来源:发表于2022-06-17 09:48 被阅读0次

哈希表的原理:空间换时间,以一个足够大的数组来实现TreeMap,key作为索引,以达到增删改查操作的时间复杂度为O(1)

哈希表的关键元素:

  • key:可以通过hash函数计算出table中的对应存放下标,hash冲突时通过equals函数对比是否是同一个key

  • table:一个足够大的数组

  • 哈希函数(散列函数):时间复杂度为O(1)的函数,可以将key转化为table中的索引

  • bucket(桶):数组元素

    • 桶可能是链表结构,也可能是红黑树结构

    • 如果存入的元素哈希值相等

利用哈希函数生成key对应的index,根据index定位table中的bucket

稳定的哈希表必须同时实现equals和hashCode,因为默认的hashCode/equals是根据地址来计算索引,因为每次存放的地址不一样,所以计算出来的结果会一直变。索引的结果可能不同,同样的索引是否覆盖值也不同。

哈希冲突(哈希碰撞),不同的key经过哈希函数得出同一个值。解决方案:

  • 开放定址法(Open Adressing)

    • 发现一个地址有值了,按照一定规则向其他地址探测,直到遇到空桶。这个规则可以是线性探测,即逐个下沿;平方探测,按平方数下沿搜索
  • 再哈希法(Re-Hashing)

    • 设计多个哈希函数
  • 链地址法(Separate Chaining)

    • 公用一个桶,通过链表将值串起来

    • 使用的是单向链表,因为存储新值,需要遍历之前的key,看是需要替换还是需要新增

哈希函数的工作原理:通过函数计算出一个整数,再用整数%table的长度,这样必然得到一个table的下标

为了提高工作效率,可以用&运算取代%,前提是桶数组(table)的长度设计为2n

index = Hash(key) & (table.length - 1)

25-1 = 100000 - 1 = 011111

  • 良好的哈希函数:哈希值更加均匀的分布,减少哈希冲突,提升哈希表性能

  • 不同类型的Key值,计算的方式也不一样,原则上尽量让元素的每一部分都参与计算

    • int:可以直接作为哈希值返回

    • 浮点数:获得浮点数内存中的二进制表示如1011011,将二进制表示作为整数值91返回。

    • long、double:

// double先转成long
- (int)hash_Code:(long)longValue {
  // 以下图为例,&运算结果变成取后面部分,|运算结果为取前面部分,不能充分结合两个部分进行计算。
    return (int)(longValue^(longValue>>32));
}


* 字符串:

Jack = j x n3+a x n2+c x n1+k x n0 = [(j x n + a) x n + c] x n + k

一般情况下 n = 31,因为31是一个奇素数,31 x i 可以优化成 (i << 5)- i

// jack = 3254239 
- (NSInteger)getHashCodeWith:(NSString*)str {
    NSInteger length = str.length;
    NSInteger index = 0;
    NSInteger hashCode = 0;
    NSInteger n = 31;
    if (length >= 2) {
        NSString *num1Str = [str substringWithRange:NSMakeRange(0, 1)];
        NSInteger num1 = [num1Str characterAtIndex:0];
        NSString *num2Str = [str substringWithRange:NSMakeRange(1, 1)];
        NSInteger num2 = [num2Str characterAtIndex:0];
        hashCode = num1 * n + num2;
        
        str = [str substringFromIndex:2];
    }
    // 如果后面还有数,那么 *n + 后面的数,进入下一个循环
    while (str.length > 0) {
        NSString *num1Str = [str substringWithRange:NSMakeRange(0, 1)];
        NSInteger num1 = [num1Str characterAtIndex:0];
        hashCode = hashCode * n + num1;
        index += 1;
        str = [str substringFromIndex:1];
    }
    return hashCode;
}

自定义对象的哈希函数

根据对象的每个属性的类型,获取各自的哈希值,将这些哈希值按字符串的哈希值获取方式来组合生成新的哈希值:

((属性1的哈希值 * 31 + 属性2的哈希值)* 31 + 属性3的哈希值) * 31 + 属性4.....以此类推

相关文章

  • 11.哈希表

    哈希表的原理:空间换时间,以一个足够大的数组来实现TreeMap,key作为索引,以达到增删改查操作的时间复杂度为...

  • Java数据结构_哈希表_基本概念

    本文目标 哈希表的基本概念,哈希冲突,哈希函数 什么是哈希表 哈希表也叫做散列表(hash有剁碎的意思)哈希表是空...

  • redis数据结构--字典

    Redis的字典底层就是哈希表。 哈希表 首先给出哈希表的定义: 其中可以看到,table是一个哈希表节点的数组,...

  • 哈希表和链表

    优秀文章:Chapter: 散列表(哈希表) 一、哈希表 哈希表hashtable(key,value) 就是把K...

  • 算法-哈希表算法总结

    1 哈希表模拟 思路:通过设计哈希表,模拟O(1)时间复杂度的哈希表。 2 数组作为哈希表 思路:数组就是简单的哈...

  • 数据结构 -- 哈希表及其应用

    这篇主要用来记录一下学习到的关于哈希表的知识点。 文章结构 哈希表 哈希表的定义 哈希表的优缺点 哈希碰撞 负载因...

  • 数据结构与算法(第一季):哈希表(Hash Table)

    一、哈希表(Hash Table) 1、概念 哈希表也叫做散列表。 哈希表的原理: 利用哈希函数生成key对应的i...

  • 深入理解哈希表

    深入理解哈希表 深入理解哈希表

  • 2019 算法面试相关(leetcode)--哈希表

    哈希表相关的原理可以参考下:浅谈哈希表(HashTable)深入理解哈希表哈希表的理解理解HashSet及使用 哈...

  • Redis中的字典

    Redis中的字典 Redis中的字典使用哈希表作为底层实现,一个哈希表中可以有多个哈希表结点,而每个哈希表结点保...

网友评论

      本文标题:11.哈希表

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