哈希函数详解(一)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希函数详解(一)相关的知识,希望对你有一定的参考价值。

参考技术A Hash(哈希),又称“散列”。

散列(hash)英文原意是“混杂”、“拼凑”、“重新表述”的意思。

在某种程度上,散列是与排序相反的一种操作,排序是将集合中的元素按照某种方式比如字典顺序排列在一起,而散列通过计算哈希值,打破元素之间原有的关系,使集合中的元素按照[散列函数]的分类进行排列。

在介绍一些集合时,我们总强调需要重写某个类的 equals() 方法和 hash Code() 方法,确保唯一性。这里的 hash Code() 表示的是对当前对象的唯一标示。计算 hash Code 的过程就称作 哈希。

我们通常使用数组或者链表来存储元素,一旦存储的内容数量特别多,需要占用很大的空间,而且在 查找某个元素 是否存在的过程中,数组和链表都需要挨个循环比较,而通过 哈希 计算,可以大大 减少比较次数 。

举个栗子:

现在有 4 个数 2,5,9,13,需要查找 13 是否存在。

这样需要遍历 4 次才能找到,时间复杂度为 O(n)。

四个数 2,5,9,13 对应的哈希值为:

然后把它们存储到对应的位置。

当要查找 13 时,只要先使用哈希函数计算它的位置,然后去那个位置查看是否存在就好了,本例中只需查找一次,时间复杂度为 O(1)。

因此可以发现,哈希 其实是随机存储的一种优化,先进行分类,然后查找时按照这个对象的分类去找。

哈希通过一次计算大幅度缩小查找范围,自然比从全部数据里查找速度要快。

比如你和我一样是个剁手族买书狂,家里书一大堆,如果书存放时不分类直接摆到书架上(数组存储),找某本书时可能需要脑袋从左往右从上往下转好几圈才能发现;如果存放时按照类别分开放,技术书、小说、文学等等分开(按照某种哈希函数计算),找书时只要从它对应的分类里找,自然省事多了。

哈希的过程中需要使用哈希函数进行计算。

哈希函数是一种映射关系,根据数据的关键词 key ,通过一定的函数关系,计算出该元素存储位置的函数。

表示为:

address = H [key]

哈希的过程中需要使用哈希函数进行计算。

哈希函数是一种映射关系,根据数据的关键词 key ,通过一定的函数关系,计算出该元素存储位置的函数。

表示为:

address = H [key]

取关键字或关键字的某个线性函数值为散列地址。

即 H(key) = key 或 H(key) = a*key + b,其中a和b为常数。

取关键字被某个不大于散列表长度 m 的数 p 求余,得到的作为散列地址。

即 H(key) = key % p, p < m。

当关键字的位数大于地址的位数,对关键字的各位分布进行分析,选出分布均匀的任意几位作为散列地址。

仅适用于所有关键字都已知的情况下,根据实际应用确定要选取的部分,尽量避免发生冲突。

先计算出关键字值的平方,然后取平方值中间几位作为散列地址。

随机分布的关键字,得到的散列地址也是随机分布的。

将关键字分为位数相同的几部分,然后取这几部分的叠加和(舍去进位)作为散列地址。

用于关键字位数较多,并且关键字中每一位上数字分布大致均匀。

选择一个随机函数,把关键字的随机函数值作为它的哈希值。

通常当关键字的长度不等时用这种方法。

构造哈希函数的方法很多,实际工作中要根据不同的情况选择合适的方法,总的原则是 尽可能少的产生冲突 。

通常考虑的因素有 关键字的长度 和 分布情况 、 哈希值的范围 等。

如:当关键字是整数类型时就可以用除留余数法;如果关键字是小数类型,选择随机数法会比较好。

以上是关于哈希函数详解(一)的主要内容,如果未能解决你的问题,请参考以下文章

Go-哈希函数与消息认证详解(含代码)

哈希表(hash)详解

C/C++手撕哈希表详解

区块链与密码学第5-5讲:详解常用哈希函数

区块链与密码学第5-4讲:详解常用哈希函数

Hash 表详解(哈希表)