码迷,mamicode.com
首页 > 其他好文 > 详细

查找:哈希表

时间:2020-07-06 16:38:44      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:图片   负载   加密   orange   相加   分析   组成   使用   hmac   

散列表(Hash),又名哈希,java中的HashMap,python中的dict,在一般代码中多用于键值对字典存储中。在查找中,哈希表的查找往往都是\(Olog(1)\),这说明哈希表的查找往往并不需要什么循环结构,是直接得出来的,那么其中必然有值和存储位置的对应计算方法,在哈希表中被叫做散列函数。有计算方法,就会出现结果的值相同的情况,对于计算结果相同的情况,哈希表也有处理这种冲突的方法。经过这俩步,就能建立键值对唯一的对应。

散列函数

留余数法,此方法使用最多,主要是它往往可以应用到其他方法中,并且它也非常的简单,只需要将值与选定值取余即可,假设选定值为\(P\),那么公式如下:

\[H(key) = key \% P \]

这里最主要的就是选定值\(P\)如何取值,一般而言,\(P\)的值接近或者等于散列表的表长。个人感觉最麻烦的地方就是开辟一块连续的空间,并且可能事先并不知道散列表表长到底是多大。

直接定址法,这也是很简单的方法,就是取线性函数的值作为散列地址,公式就是:

\[H(key) = a\times key + b \]

这个方法好处就是没有冲突,不用处理冲突了,但是线性函数计算的结果可能很大,这样不连续,就会造成空间的浪费,留下很多空位。

数字分析法,这就是分析输入的数,一般用于输入的数较长,比如身份证,那么可以分析身份证上的数字,使用其中的一段作为唯一的,比如身份证后六位。

折叠法,折叠就是将数字分成几部分,然后再将这几部分值进行相加。这个分成几部分之后,还可以进行其他的一些处理。

平方取中法,就是将关键字进行平方,之后取中间几位,不过个人感觉这个方法还是用于数字较多的情况下,并且到底取几位要根据情况确定。

值在经过上面的散列函数之后,计算出来的结果可能相同,这时候对于这种相同结果就要处理冲突。

处理冲突的方法

开放定址法,在发生冲突的时候,再找其他的位置来存下发生冲突的关键字,这种处理方式通常有好几种取法:

  1. 线性探测法,在发生冲突后,顺序查探下一个单元,直到找到一个空闲位置。这种方法缺点就是容易堆积在一起,大大降低了查询效率。
  2. 平方探测法,上面那个容易堆积在一起,因而在查找下一个位置的时候,使用平方查找位置,将数据分散,\(1^2,-1^2,2^2,-2^2,\dots ,k^2,-k^2\),这样导致的问题就是不能探测到全部的位置。
  3. 再散列探测法,这个就是再来一个散列函数。当第一个发生冲突了,再利用第二个散列函数计算该关键字的位置。
    拉链法,也叫链表法,就是将发生冲突的数据存储在同一个线性链表中,适合经常插入和删除的情况。个人感觉这种方法也很有效果
技术图片
图1. 拉链法处理的散列表

总结

书中说,哈希表的查找效率取决于三个方面:散列函数,处理冲突的方法和装填因子。其中装填因子就是哈希表中的数据多少,如果装的越多,那么就越容易发生冲突,反之发生冲突的概率就越小。但是以前我看很多分析哈希表都是直接得出来的。

哈希表不仅仅是用于存储数据中,更多的是用于其他领域中,比如密码学中,因为很多时候保存明文密码是不安全的,所以很多为了保护用户密码信息,都会保存密码的hash值。其中的方法有MD5,但是这样搞出来的hash值还是可以破解的,最简单的暴力破解。针对这种情况,采取的办法就是加盐salt,就是用特殊字符和用户输入的密码一起组成一个新的字符,但是如果salt被泄露了,那么就要修改全部的信息,针对这个问题,使用的是HMAC加密,加密使用的key是从服务器端获取的,每个用户都不一样。

哈希也可以用于数据检验中,比如git中的提交。每次提交都会有一个id,这个id就是SHA-1算法计算出来的,也可以用于负载均衡。

以前在学习爬虫的,为了标记已经爬过的网页,会使用到布隆过滤器,在数学之美这本书中介绍过这种方法,布隆过滤器也是哈希实现的。

查找:哈希表

标签:图片   负载   加密   orange   相加   分析   组成   使用   hmac   

原文地址:https://www.cnblogs.com/mary1/p/13255100.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!