算法入门:Hash

什么是Hash算法:#####

简单的说,hash算法就是将字符串转化为数字的算法。

用一个例子说Hash的优势#####

试想如果我们对一个数组进行Query,这个数组里,每一个元素都是一个字符串。我们知道数组最快的检索办法是通过数组的下标进行检索,但是对于这种场景,我们无能为力,只能从头查到尾,从而查询出目标元素。


Paste_Image.png

假设,我要找gaofei,那就需要遍历整个数组,十分的低效。这样最坏情况下时间复杂度是O(n)的,但是数组的查询时间复杂度是O(1)的(下标查询),那有没有一种方法能达到O(1)的时间复杂度呢?有!那就是用 Hash。
我们需要达到O(1)的时间复杂度,那无疑使用数组的下标查找。那么我们就需要将存储的元素转化为数组的下标。
那怎么设计hash函数呢?我们用一种最笨的方法,将所有字符串中的字符转化为数字后相加。那ok,我们简单的实现下。
zhangsan=>hash()=>858
lisi=>hash()=>433
wanger=>hash()=>644
wangwu=>hash()=>665
zhangsi=>hash()=>756
gaofei=>hash()=>619
这样,我们就计算出来了每一个字符串对应的数字映射了,我们叫这个数字为hash值,接下来我们再放到数组里:

Paste_Image.png

上图中数组的下标就是字符串对应的数字值。这下我们查找gaofei就很容易了,首先我们根据hash函数计算出gaofei的位置为619,然后去数组的619中找到gaofei,这样时间复杂度就是O(1)啦。

hash冲突(拉链法):#####

但是上面的实现是存在一个问题的,如果还有一个元素叫feigao会怎么样?
我们首先计算下feigao的hash值,计算结果竟然和gaofei一样,也是619。这下产生了Hash冲突了,怎么办?619已经有gaofei了,feigao放在哪?所以接下来我们只能改变数组的结构了,怎么改变?我们将数组内的元素改变为一个链表,这样就能装下足够多的元素了。这样就能解决hash冲突的问题了:

Paste_Image.png

如上图,我们将冲突的元素变为了链表结构,这样我们就能把feigao也放在了这个table结构里面,其实这个数据结构就叫做Hash表(HashTable)。
我们在检索的时候可以这样检索

Paste_Image.png

找到gaofei后,我们便可以遍历链表,找到feigao了。是不是很开森?

怎样压缩hash表#####

但是,问题又来了,上面的数组好像不是很连续啊,从433直接跳到了619.中间的数组都浪费了啊!!!。其实也不能说是浪费,只不过暂时没有用啊,如果没有对应的元素出现,就这样一直浪费着?显然是不可取的。那我们想办法压缩下这个数组。
其实很简答,只要减小hash值就行了嘛,那么我们对hash值取模,这样就能保证所有的hash值落在模值之内了。
但是对于取模的运算计算机通常用位运算是更快的,例如java的HashMap的默认容量是16,每次扩容之后也都维持2^n,为什么呢?
对于取模运算hashMap是这样实现的hashcode& (length-1)。如果length为16,那么正好是hashcode&15,例如feigao这个计算吧:
hash值:619 => ...0001001101011
length-1:15 => ...0000000001111
二者做与运算结果为:...000000001011 => 11(十进制)
其实可以口算一下结果为38余11(注意这里是除16而不是15)。同理对于32也是一样的。但是这里有一个很著名的问题,就是因为数字的不均匀会导致hash值的二进制数末尾都是1的这种场景。这种场景会导致很多的值集中在最后一个数组元素,从而分布不均匀。解决方案是对hash值进行重新计算hash。这种机制比较复杂。至今没搞懂。
这里主要是考虑这样设计主要考虑计算速度会十分的快,根据不同实现这个容量也是不固定的,这里只是以java的HashMap为例。

用几个例子说一下HashTable的用处:#####
Case1:两文件找出重复的元素#####

问题是这样的,有两个文件,文件中有一些短字符串,字符串个数分别为n。它们是有重复的字符串,现在需要找出所有重复的字符串。
首先我们考虑最笨的方法,遍历文件1中的每个元素,取出每一个元素分别去文件2中进行查找,这样的时间复杂度为O(n^2)
接下来我们使用HashTable,我们遍历文件1中的元素和文件2中的元素,放入HashTable中,对于重复的字符串我们做计数处理:

Paste_Image.png

接下来遍历整个列表,找出所有个数大于1的即为重复的元素。

Case2:两文件找出出现次数最多的元素#####

和上面是同理的,但是在遍历的时候需要找计数最大的元素,即为出现次数最多的元素。

Case3:路由算法#####

在一个多线程处理数据的场景下,我们需要将一个数据集分给不同的处理线程,同时要保证,相同的元素需要分到相同的处理线程上去,那么我们怎么处理呢?
其实这个就是一个很典型的Hash值应用场景,对于很多的计算引擎默认都是用hash算法去解决这个问题。因为相同元素的Hash值相同,那么我们可以取hash之后进行模运算,运算结果分配到不同的线程:

Paste_Image.png
Hash算法的要点#####

在设计Hash算法的时候。一定要保证相同字符串产生的Hash值相同,同时要尽量的减小Hash冲突的发生(虽然避免不了)。这样才是一个好的hash算法。目前,MurmurHash是一种冲突率最低的Hash算法。如果有需要,可以优先考虑此算法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,637评论 24 1,002
  • 作者:July、wuliming、pkuoliver 说明:本文分为三部分内容,第一部分为一道百度面试题Top K...
    cyj_ya阅读 797评论 0 0
  • 四 情不知所起 不知道为什么,萧桐挡在林晓菲前面的那一幕在林晓菲心里演了一遍又一...
    小鱼儿的写字台阅读 213评论 1 7
  • (一)only 修饰谁,就放谁前面 正选A 正选C (二)Ving放句首表示主动 与主语搭配,选A (三)Ved放...
    Emily爷阅读 311评论 0 0
  • 昨天中午,饭后,本来很瞌睡的,看完了今日说法,惯性的要小睡会儿,突然的,想起老师嘱咐过要求看看《当幸福来敲...
    a85d99ff3e56阅读 411评论 0 0