哈希算法、哈希表的作用与原理

闲谈Hash

由于以前对hash的理解就不是很透彻,与是在工作不忙的时候,回首掏了一波hash,并记录一下自己的心得体会。

哈希算法和哈希表都不是自然产生的,都是人为的产物,既然是人为了的,那么就可以跟随创造它的目的去深入理解它。

哈希算法的最初是为了验证两条信息是否相同,可能你会认为这很简单啊,所有的编程语言都提供的有比较的方法,直接用不就可以了吗,确实,是可以直接用一些类似于equals等方法去比较,但是这些方法底层几乎都是将两个字符串的每一个字符进行比较(为什么说是字符串呢,因为所有的东西可以认为是0和1组成的字符串,你说要是数字,那也行,不过大的让你无法想象)

这里你需要改变一下认识,即万物皆“字符串”,咱往最底层的去看,所有的语言都有共同的底层(0和1)。两条信息要进行比较是否相同,要对两条信息最终的机器码进行亦或运算,结果为零时说明两条信息一样。现在的机器一般都位64位的机器,一次只能处理64位的数据,一个1G的信息的机器码可能长达几十上百亿或更长,两条这样的信息进行比较时,这需要计算机去运算很多很多很多次,会发费大量的时间。(不要问我为什么会有1G的信息,因为万物皆“信息”,一句话算是一条信息,一个文件也可以算是一条信息)

Hash 算法

Hash算法的规则要求先不提,最后再说,不然很容易懵逼。

hash算法就是经过一系列简单的操作(这个指的是计算机和牛逼的数学家认为的简单,对于非数学家的我们来说.....)让一条信息变短,这样说不太准确,因为并没有改变这条信息,而是类似与给这条信息起了个别名,这个别名就像你与你的身份证号一样,具有唯一性。这个别名远远短于这条信息,所以比较两条信息时可以比较它们的别名,如果两条信息别名一样,那就说明这两天信息是一样的了。所以这个别名很重要,对于两条相同的信息必须要产生一致的别名,所以起别名不能随意起,需要有一定的规则,这个规则统称Hash算法。

接下来是Hash的三个规则:

  1. 将任何一条不论长短的信息,计算出唯一的一串数字与它相对应;
  2. 这串数字的长度必须固定;
  3. 这串数字不可能再被反向破译。也就是说,我们只能把原始的信息转化为这串数字,而不可能将这串数字反推回去得到原始信息

逐条进行解释:第一条很容易理解,每一条信息都应该有自己独一无二的别名,不能存在重名的现象(别跟我说世界上重名的很多,咱们的姓名只是代号,咱们的唯一标识是身份证号,你见过身份证号一样的两个人吗?)。

第二条的原因跟计算机有关,更要理解什么是无穷,一个算法的输入是无穷的,要让每个不同的输入都有一个唯一的输出(别名),那么这个算法的输出也是无穷的。然而,计算机并没有办法去处理无穷,计算机只能处理有限的数据,解决不了无限的数据。所以要规定一下,这个算法的输出长度必须固定。(挑刺的人一定会问,那为啥不是算法输出结果的最大长度固定呢,对于这个问题需要你去思考1与0....001的区别了)。固定算法的输出长度后,计算机是可以处理算法的输出了,但是这也造成了一个无法解决的问题,无穷的输入,有穷的输出,又要要求输入与输出对应,理论上是一定会产生冲突的,即在无穷的输入里,有多个输入会输出相同的值。所以会有一些解决冲突的方法,但是这个冲突在理论上是永远无法避免的,各种解决冲突的办法只不过是去无限降低冲突的概率。

第三条的存在是为了安全性,因为hash算法这么牛逼的东西,肯定会用在军事和商业上面啊,而且哈希算法这个东西就是美国安全局在1993年(哈希算法的年龄比我都还大)搞出来的。所以为了信息安全,所以才有了第三条规则。不过如同第二条一样,第三条在数学上也是有bug的,在数学上任何函数都是可逆性的,哈希算法也是函数,理论上它必然可逆。既然如此,那为什么还会有第三条呢?因为理论始终是理论,理论上是可逆的,你通过哈希的输出去逆运算是可以算出它的输入的,前提是你得有超级牛逼的电脑和比乌龟还长的寿命。所以第三条的不可逆是指现实中的不可逆。

Hash冲突

Hash冲突,我举个栗子,MD5大家应该都听说过,额...没听过的就算了,MD5是一种哈希算法,广泛用于杀毒软件中,杀毒软件公司自己有一个数据库,里面存放各种已知的病毒(计算机的)的MD5码,在你使用杀毒软件进行扫描的时候,杀毒软件会对你电脑上的所有文件进行哈希运算,得到每个文件的MD5码,然后与它数据库里已知的MD5码进行对比,对比上了(恭喜你,喜提木马一只),杀毒软件就会将这个文件删除掉。但是有时候,不是病毒的文件也会被杀毒软件干掉(可以去买彩票了),就是因为你这个文件的MD5码和某个病毒的MD5码一样。

//下面这段话可能会误导小白们,可以不用管。之所以不删除这段话是因为,这段话有助于我自己对hash的理解。

Hash冲突我个人分为两种,一种是结果冲突,一种是过程冲突。过程冲突是在哈希算法的设计过程中,对于不同的输出经过算法运算后有相同的结果,这个时候就要对冲突进行处理,常见的处理方法有开放地址法,线性推理法,溢出池法,二次哈希法等等,这些方法的目的就是降低最终的结果冲突,注意是降低不是解决,因为无穷/有穷>1,最终结果的冲突永远会存在。

 

Hash表

上面在说Hash函数的时候从宏观(字符串,文件...)直接忽视所有中间过程到机器码,这里稍微写一些中间的东西,内存地址。Hash函数用的最多的我想应该是在寻址方面。通过上面所说,哈希函数的作用就是在两条信息进行比较时,通过数学方法,降低计算机进行比较所耗费的时间。计算机进行两条信息的比较发生最多的地方就是内存寻址上了。以JAVA语言来说,你定义一个变量 a ,在栈中会有一个内存的地址指向变量a,当你给a赋值的时候,赋的值会存放在内存中对应的存储单元里。不管是存数据还是取数据,都会有地址的比较。使用hash算法后,地址还是需要同等次数的比较,但是每次比较都节省了一点时间,这一丢丢的时间在比较的次数很大时,节省的时间就很可观,时间就是效率,节省时间就是最大的优化。

下面是Hash表的百度百科解释,看完上面的内容之后,百度百科的解释就很容易理解了:

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值