哈希游戏- 哈希游戏平台- 哈希游戏官方网站直接定址法的缺点也非常明显,当关键字的范围比较分散时,就很浪费内存甚至内存不够用。假设我们只有数据范围是[0,9999]的N个值,我们要映射到⼀个M个空间的数组中(⼀般情况下M=N),那么就要借助哈希函数(hash function)hf,关键字key被放到数组的h(key)位置,这里要注意的是h(key)计算出的值必须在[0, M)之间。 这里存在的⼀个问题就是,两个不同的key可能会映射到同⼀个位置去,这种问题我们叫做哈希冲突,或者哈希碰撞。理想情况是找出⼀个好的哈希函数避免冲突,但是实际场景中,冲突是不可避免的,所以我们尽可能设计出优秀的哈希函数,减少冲突的次数,同时也要去设计出解决冲突的⽅案。
当使用除法散列法时,要尽量避免M为某些值,如2的幂,10的幂等。如果是2的X次方 ,那么key %2的X次方本质相当于保留key的后X位,那么后x位相同的值,计算出的哈希值都是⼀样的,就冲突了。如:{63,31}看起来没有关联的值,如果M是16,也就是2的4次方 ,那么计算出的哈希值都是15,因为63的⼆进制后8位是00111111,31的⼆进制后8位是00011111。如果是10的X次方,就更明显了,保留的都是10进值的后x位,如{112,12312},如果M是100,也就是10的平方 ,那么计算出的哈希值都是12。
需要说明的是,实践中也是八仙过海,各显神通,Java的HashMap采用除法散列法时就是2的整数次幂做哈希表的大小M,这样玩的话,就不用取模,而可以直接位运算,相对而言位运算比模更高效⼀些。但是他不是单纯的去取模,比如M是2^16次方,本质是取后16位,那么用key=key16,然后把key和key异或的结果作为哈希值。也就是说我们映射出的值还是在[0,M)范围内,但是尽量让key所有的位都参与计算,这样映射出的哈希值更均匀⼀些即可。所以上面建议M取不太接近2的整数次幂的⼀个质数的理论是大多数数据结构书籍中写的理论吗,但是实践中,灵活运用,抓住本质。
保证h2 (key) 与M互质是因为根据固定的偏移量所寻址的所有位置将形成⼀个群,若最大公约数p = gcd(M, h1 (key)) 1 ,那么所能寻址的位置的个数为M/P M ,使得对于⼀个关键字来说无法充分利用整个散列表。举例来说,若初始探查位置为1,偏移量为3,整个散列表大小为12,那么所能寻址的位置为{1, 4,7,10},寻址个数为12/gcd(12, 3) = 4
这里我们哈希表负载因子控制在0.7,当负载因子到0.7以后我们就需要扩容了,我们还是按照2倍扩容,但是同时我们要保持哈希表大小是⼀个质数,第⼀个是质数,2倍后就不是质数了。那么如何解决了,⼀种⽅案就是上面1.4.1除法散列中我们讲的Java HashMap的使用2的整数幂,但是计算时不能直接取模的改进方法。另外⼀种方案是sgi版本的哈希表使勇的方法,给了⼀个近似2倍的质数表,每次去质数表获取扩容后的大小
当key是string/Date等类型时,key不能取模,那么我们需要给HashTable增加⼀个仿函数,这个仿函数支持把key转换成⼀个可以取模的整形,如果key可以转换为整形并且不容易冲突,那么这个仿函数就⽤默认参数即可,如果这个Key不能转换为整形,我们就需要自己实现⼀个仿函数传给这个参数,实现这个仿函数的要求就是尽量key的每值都参与到计算中,让不同的key转换出的整形值不同。string做哈希表的key非常常见,所以我们可以考虑把string特化⼀下。
哈希是一种通过特定函数将任意长度的输入数据映射为固定长度输出的技术,其核心思想是将数据的关键字经过哈希函数计算后转换为存储位置的索引,从而实现高效的数据访问。哈希表作为哈希的典型应用,通常由数组与链表结合实现,数组用于快速定位桶的位置,链表则用于处理哈希冲突。当不同关键字经过哈希函数计算后得到相同的索引时,即发生冲突,常见解决方法包括开放寻址法和链地址法:开放寻址法通过线性探测、二次探测等方式在数组中寻找下一个空闲位置,而链地址法则将冲突元素以链表形式存放在同一桶中,两种方法各有优劣,前者节省空间但易产生聚集现象,后者处理简单但需要额外内存存储指针。
哈希的应用场景广泛,例如数据库索引通过哈希加速查询,缓存系统(如Redis)利用键值对存储实现快速数据读写,唯一标识生成(如短链接服务)依赖哈希压缩数据,而数据校验(如MD5、SHA系列算法)则利用哈希的不可逆性验证完整性。在密码学中,哈希需满足抗碰撞性与雪崩效应等严格特性,与常规哈希相比更注重安全性。哈希的性能高度依赖函数设计,优秀的哈希函数需确保输出分布均匀、计算高效,同时结合动态扩容机制(如负载因子超过阈值时进行再哈希)以避免频繁冲突。虽然哈希表在理想情况下可实现O(1)时间复杂度,但设计不当可能导致最坏情况退化为O(n),例如当所有元素集中到同一桶时。实际开发中,Java的HashMap采用链地址法结合红黑树优化,Python字典则使用开放寻址法提升缓存局部性。值得注意的是,哈希虽适合精确查找,却无法支持范围查询,这一局限性常通过结合其他数据结构(如B+树)来弥补。在分布式系统中,一致性哈希通过环形映射解决节点扩缩容时的数据迁移问题,进一步扩展了哈希的应用边界。