散列表(哈希表)的基本原理

上面 HashSet 和 HashMap 都使用了 散列表來做數(shù)據(jù)的檢索吟温,那么什么是散列表 ,這個(gè)又有什么優(yōu)點(diǎn)呢 ?

散列表也叫作哈希表(hash table)谈山,這種數(shù)據(jù)結(jié)構(gòu)提供了鍵(Key)和值(Value)的映射關(guān)系智亮。只要給出一個(gè)Key忆某,就可以高效查找到它所匹配的Value,時(shí)間復(fù)雜度接近于O(1)阔蛉。

是不是想到了 Map 弃舒?

散列表是如何根據(jù)Key來快速找到它所匹配的 Value 呢 ?

在目前所學(xué)的數(shù)據(jù)結(jié)構(gòu)中状原,數(shù)組的查詢效率是最高的聋呢。散列表本質(zhì)就是一個(gè)數(shù)組。不同的是數(shù)組的下標(biāo)是數(shù)字颠区,但是散列表的下標(biāo)是字符串削锰。這就需要設(shè)計(jì)一個(gè)中轉(zhuǎn)站,通過某種方式毕莱,把Key和數(shù)組下標(biāo)進(jìn)行轉(zhuǎn)換器贩。這個(gè)中轉(zhuǎn)站就叫作哈希函數(shù)

圖1.png

在不同的語言中朋截,哈希函數(shù)的實(shí)現(xiàn)是不一樣的蛹稍。我們以Java的HashMap為例,來看看哈希函數(shù)的實(shí)現(xiàn)部服。
在Java及大多數(shù)面向?qū)ο蟮恼Z言中唆姐,每一個(gè)對象都有屬于自己的hashcode,這個(gè)hashcode是區(qū)分不同對象的重要標(biāo)識廓八。無論對象自身的類型是什么奉芦,它們的hashcode都是一個(gè)整型變量胆描。
既然都是整型變量,想要轉(zhuǎn)化成數(shù)組的下標(biāo)也就不難實(shí)現(xiàn)了仗阅。最簡單的轉(zhuǎn)化方式是什么呢昌讲?是按照數(shù)組長度進(jìn)行取模運(yùn)算
<

index = HashCode (Key) % Array.length

其實(shí)JDK中的哈希函數(shù)為了提升效率,使用的是位運(yùn)算减噪。我們就假設(shè)使用的是模運(yùn)算
通過哈希函數(shù)短绸,我們可以把字符串或其他類型的Key,轉(zhuǎn)化成數(shù)組的下標(biāo)index筹裕。如給出一個(gè)長度為8的數(shù)組醋闭,則當(dāng)
key=001121時(shí)

index = HashCode ("001121") % Array.length = 1420036703 % 8 = 7

而當(dāng)key=this時(shí),

index = HashCode ("this") % Array.length = 3559070 % 8 = 6

散列表的讀寫操作

寫操作就是在散列表中插入新的鍵值對(在JDK中叫作Entry)朝卒。如調(diào)用hashMap.put("002931", "王五")证逻,意思是插入一組Key為002931、Value為王五的鍵值對抗斤。具體該怎么做呢囚企?

  1. 通過哈希函數(shù),把Key轉(zhuǎn)化成數(shù)組下標(biāo)5瑞眼。

  2. 如果數(shù)組下標(biāo)5對應(yīng)的位置沒有元素龙宏,就把這個(gè)Entry填充到數(shù)組下標(biāo)5的位置


    篇.png

    由于數(shù)組的長度是有限的,當(dāng)插入的Entry越來越多時(shí)伤疙,不同的Key通過哈希函數(shù)獲得的下標(biāo)有可能是相同的银酗。例如002936這個(gè)Key對應(yīng)的數(shù)組下標(biāo)是2;002947這個(gè)Key對應(yīng)的數(shù)組下標(biāo)也是2徒像。


    圖片.png

這種情況黍特,就叫作哈希沖突

解決哈希沖突的方法主要有兩種,一種是開放尋址法锯蛀,一種是鏈表法

  1. 開放尋址法的原理很簡單灭衷,當(dāng)一個(gè)Key通過哈希函數(shù)獲得對應(yīng)的數(shù)組下標(biāo)已被占用時(shí),我們可以“另謀高就”谬墙,尋找下一個(gè)空檔位置
  2. HashMap數(shù)組的每一個(gè)元素不僅是一個(gè)Entry對象今布,還是一個(gè)鏈表的頭節(jié)點(diǎn)。每一個(gè)Entry對象通過next指針指向它的下一個(gè)Entry節(jié)點(diǎn)拭抬。當(dāng)新來的Entry映射到與之沖突的數(shù)組位置時(shí)部默,只需要插入到對應(yīng)的鏈表中即可


    圖片1.png

讀操作(get)

讀操作就是通過給定的Key,在散列表中查找對應(yīng)的Value造虎。例如調(diào)用 hashMap.get("002936")傅蹂,意思是查找Key為002936的Entry在散列表中所對應(yīng)的值

  1. 通過哈希函數(shù),把Key轉(zhuǎn)化成數(shù)組下標(biāo)2。
  2. 找到數(shù)組下標(biāo)2所對應(yīng)的元素份蝴,如果這個(gè)元素的Key是002936犁功,那么就找到了;如果這個(gè)Key不是002936也沒關(guān)系婚夫,由于數(shù)組的每個(gè)元素都與一個(gè)鏈表對應(yīng)浸卦,我們可以順著鏈表慢慢往下找,看看能否找到與Key相匹配的節(jié)點(diǎn)案糙。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末限嫌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子时捌,更是在濱河造成了極大的恐慌怒医,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奢讨,死亡現(xiàn)場離奇詭異稚叹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拿诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門扒袖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人佳镜,你說我怎么就攤上這事僚稿。” “怎么了蟀伸?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缅刽。 經(jīng)常有香客問我啊掏,道長,這世上最難降的妖魔是什么衰猛? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任迟蜜,我火速辦了婚禮,結(jié)果婚禮上啡省,老公的妹妹穿的比我還像新娘娜睛。我一直安慰自己,他們只是感情好卦睹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布畦戒。 她就那樣靜靜地躺著,像睡著了一般结序。 火紅的嫁衣襯著肌膚如雪障斋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音垃环,去河邊找鬼邀层。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遂庄,可吹牛的內(nèi)容都是我干的寥院。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼涛目,長吁一口氣:“原來是場噩夢啊……” “哼秸谢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泌绣,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钮追,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后阿迈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體元媚,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年苗沧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刊棕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡待逞,死狀恐怖甥角,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情识樱,我是刑警寧澤嗤无,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站怜庸,受9級特大地震影響当犯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜割疾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一嚎卫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宏榕,春花似錦拓诸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涌献,卻和暖如春胚宦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工枢劝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留井联,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓您旁,卻偏偏與公主長得像烙常,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子鹤盒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 散列表也叫作哈希表(hash table)蚕脏,這種數(shù)據(jù)結(jié)構(gòu)提供了鍵(Key)和值(Value)的映射關(guān)系。只要給出一...
    呂艷凱閱讀 773評論 0 0
  • 散列表(也叫哈希表)侦锯,是根據(jù)鍵而直接訪問在內(nèi)存存儲位置的數(shù)據(jù)結(jié)構(gòu)驼鞭。在這篇文章中,我們將介紹散列表的基本原理尺碰。通過了...
    王聰帥閱讀 2,940評論 0 7
  • 什么是哈希表挣棕? 哈希表(Hash table,也叫散列表)亲桥,是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問的數(shù)...
    奧斯特洛司機(jī)閱讀 342評論 0 1
  • 什么是哈希表洛心? 哈希表(Hash table,也叫散列表)题篷,是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問的數(shù)...
    郝程序猿閱讀 2,239評論 1 7
  • 散列表 在前面我們已經(jīng)知道词身,我們可以使用數(shù)組中的下標(biāo)對數(shù)據(jù)進(jìn)行定位,這種定位方式非撤叮快速法严。但是在數(shù)組定位中有一個(gè)局...
    天命_風(fēng)流閱讀 535評論 2 0