哈希表—哈希函數(shù)的設(shè)計

冰凍非一日之寒

上一篇文章中,我們舉了身份證號為關(guān)鍵字的例子闷愤。這里整葡,我們假設(shè)真的有一個無限大的空間,那么讥脐,可以直接將身份證號作為索引嗎遭居?

顯然不合適。因為旬渠,并不是所有的身份證號都是18位的俱萍,對于那些位數(shù)在17位以下的,就太浪費這個大空間了告丢。

設(shè)計哈希函數(shù)的原則是枪蘑,將我們所關(guān)心的鍵通過哈希函數(shù)求出索引,“鍵”通過哈希函數(shù)得到的“索引”分布越均勻越好(實際上芋齿,實現(xiàn)起來非常困難)

那么腥寇,對于像身份證號這樣的大整數(shù)為關(guān)鍵字時,該怎么計算對應(yīng)的索引呢觅捆?

或者像復(fù)合類赦役、字符串、浮點數(shù)這樣類型的關(guān)鍵字栅炒,該如何計算它們對應(yīng)的索引呢掂摔?

對于哈希函數(shù)來說术羔,我們只能將整型數(shù)據(jù)作為關(guān)鍵字來求解索引。所以乙漓,不管什么類型的關(guān)鍵字级历,我們應(yīng)該先將其轉(zhuǎn)化為整型類型的數(shù)據(jù)。

按照這個思路叭披,以下介紹幾種最簡單寥殖、最基礎(chǔ)、最一般涩蜘、最通用的哈希函數(shù)

整型

小范圍正整數(shù)直接使用

例如嚼贡,上一篇講的ASCII值作為關(guān)鍵字

再例如,一個班有30個學生同诫,1—30表示每位學生對應(yīng)的學號粤策,并作為關(guān)鍵字

像這樣的小范圍正整數(shù),可以直接將關(guān)鍵字作為索引误窖,存儲到數(shù)組中去

小范圍負整數(shù)進行偏移

例如叮盘,-100~100的數(shù)作為關(guān)鍵字,這時可以每個數(shù)都加上100霹俺,變?yōu)?~200的正整數(shù)

這樣柔吼,就可以將關(guān)鍵字直接作為索引存儲到數(shù)組中去

大整數(shù)取模

例如,身份證號作為關(guān)鍵字吭服,412637199707096354

取后四位(6354)嚷堡。也就是,mod 10000

假如艇棕,取后六位(096354)蝌戒。即,mod 100 0000 這樣沼琉,會分布不均勻

對于身份證號來說北苟,后六位的前兩位(09)代表著日期數(shù),也就是1~31的數(shù)字打瘪。那么友鼻,這個六位數(shù)不會達到32 0000這么大,中國這么多人口闺骚,顯然這個數(shù)字是不夠的彩扔,這也就造成了索引分布不均勻

這也就體現(xiàn)了哈希函數(shù)的復(fù)雜性,也說明了具體問題要具體分析僻爽。

上面的取模方式還有一個問題虫碉,沒有有效利用所有信息。我們這樣取模胸梆,只是利用了關(guān)鍵字的一部分敦捧,也就是不管這個人是哪個地區(qū)哪個年份出生的须板,都有可能存儲到一個地址中去,這樣會增加哈希沖突的概率兢卵。那么习瑰,該如何解決這個問題呢?

一個簡單的解決辦法:模一個素數(shù)

為什么要模一個素數(shù)呢秽荤?簡單舉個例子

圖片發(fā)自簡書App

顯然甜奄,模一個素數(shù),結(jié)果會分布的更均勻王滤,哈希沖突的概率也會變小贺嫂。我們該如何選擇這個素數(shù)呢滓鸠?相關(guān)的領(lǐng)域?qū)<乙呀?jīng)為我們研究出了答案雁乡。

圖片發(fā)自簡書App

假如,需要存儲的數(shù)在2^5~2^6之間糜俗,模上53就可以了踱稍。

注:這個表并不是唯一的,一個區(qū)間內(nèi)可以有多個素數(shù)

浮點型

將浮點型解析成大整型悠抹,之后再相應(yīng)取模(如上)

字符串

先看一個例子

圖片發(fā)自簡書App

把一個整數(shù)用科學計數(shù)法來表示珠月,同樣,字符串也可以類似表示楔敌。將這個字符串看成26進制啤挎,是因為有26個小寫字母,如果字符串中有大寫字母或者標點符號卵凑,那么看成26進制顯然是不夠的庆聘,可以看成是100進制或者256進制等。顯然勺卢,這個進制是用戶可以自己選擇的伙判,我們用 B 來表示這個進制

圖片發(fā)自簡書App


每一個小寫字母對應(yīng)一個數(shù)字,這樣我們把字符串也轉(zhuǎn)化成了大整型黑忱,之后就可以利用上面取模的方式計算哈希值了宴抚。

字符串哈希函數(shù)

這樣就可以計算出字符串的哈希值了。當B是一個比較大的數(shù)或者字符串比較長時甫煞,求B的k次方是比較浪費時間的菇曲,所以我們可以優(yōu)化這個表達式

哈希函數(shù)*優(yōu)化

這樣就省去了求次方運算。但是抚吠,還有可能會出現(xiàn)整型溢出的情況常潮,當B是一個很大的數(shù)字或者字符串很長的時候,我們可以再次優(yōu)化這個表達式

哈希函數(shù)*再次優(yōu)化

這樣埃跷,每退出一個小括號蕊玷,數(shù)字都會變成比M先得數(shù)字邮利,就不會出現(xiàn)溢出情況了

復(fù)合類

假如我們自己定義一個類,日期類

Date:year垃帅,month延届,day

為這個Date類設(shè)計哈希函數(shù),可以像字符串那樣贸诚,將類的屬性值看著是一個字符

復(fù)合類哈希函數(shù)

這樣方庭,就求出了復(fù)合類的哈希值。

求哈希函數(shù)原則

原則

一致性:當關(guān)鍵字相同時酱固,經(jīng)過哈希函數(shù)求出的哈希值也是相同的械念。

反過來是不成立的,即當哈希值相同時關(guān)鍵字不一定相同运悲。哈希值相同龄减,取模后得到的索引也相同,即不同的關(guān)鍵字對應(yīng)的存儲位置相同班眯,這也就是所謂的哈希沖突希停。

高效性:我們設(shè)計哈希函數(shù)就是為了高效存儲數(shù)據(jù),如果哈希函數(shù)的設(shè)計就消耗過多性能署隘,那么就得不償失了

均勻性:通過哈希函數(shù)求出的索引必須是分布均勻的宠能。




以上,就是轉(zhuǎn)化為整型求哈希函數(shù)磁餐。但是违崇,這并不是求哈希函數(shù)唯一的方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诊霹,一起剝皮案震驚了整個濱河市羞延,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌畅哑,老刑警劉巖肴楷,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異荠呐,居然都是意外死亡赛蔫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門泥张,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呵恢,“玉大人,你說我怎么就攤上這事媚创∩ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳄橘。 經(jīng)常有香客問我声离,道長,這世上最難降的妖魔是什么瘫怜? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任术徊,我火速辦了婚禮,結(jié)果婚禮上鲸湃,老公的妹妹穿的比我還像新娘赠涮。我一直安慰自己,他們只是感情好暗挑,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布笋除。 她就那樣靜靜地躺著,像睡著了一般炸裆。 火紅的嫁衣襯著肌膚如雪垃它。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天晒衩,我揣著相機與錄音嗤瞎,去河邊找鬼。 笑死听系,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的虹菲。 我是一名探鬼主播靠胜,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毕源!你這毒婦竟也來了浪漠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤霎褐,失蹤者是張志新(化名)和其女友劉穎址愿,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冻璃,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡响谓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了省艳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娘纷。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖跋炕,靈堂內(nèi)的尸體忽然破棺而出赖晶,到底是詐尸還是另有隱情,我是刑警寧澤辐烂,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布遏插,位于F島的核電站捂贿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胳嘲。R本人自食惡果不足惜眷蜓,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胎围。 院中可真熱鬧吁系,春花似錦、人聲如沸白魂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽福荸。三九已至蕴坪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敬锐,已是汗流浹背背传。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留台夺,地道東北人径玖。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像颤介,于是被迫代替她去往敵國和親梳星。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

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

  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,770評論 0 38
  • 一.概念 哈希表就是一種以 鍵-值(key-indexed) 存儲數(shù)據(jù)的結(jié)構(gòu)滚朵,我們只要輸入待查找的值即key冤灾,即可...
    lfp901020閱讀 2,971評論 0 2
  • 冰凍非一日之寒 java中,對于任何類型的數(shù)據(jù)調(diào)用hashCode方法都會返回一個哈希值辕近,并且這個哈希值是個整型韵吨。...
    尤奇勤_三月閱讀 1,085評論 0 0
  • 一、PyCharm的基本使用1.1移宅、注釋:為了方便自己或者其他人查看單行注釋:用 # 號單行注釋多行注釋: 用 ...
    IIronMan閱讀 8,850評論 3 18
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,093評論 1 32