淺談哈希表(HashTable)

概述

散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表。
給定表M,存在函數f(key),對任意給定的關鍵字值key,代入函數后若能得到包含該關鍵字的記錄在表中的地址,則稱表M為哈希(Hash)表,函數f(key)為哈希(Hash) 函數。

哈希表是一種通過哈希函數將特定的鍵映射到特定值的一種數據結構,他維護者鍵和值之間一一對應關系。

  • 鍵(key):又稱為關鍵字。唯一的標示要存儲的數據,可以是數據本身或者數據的一部分。
  • 槽(slot/bucket):哈希表中用于保存數據的一個單元,也就是數據真正存放的容器。
  • 哈希函數(hash function):將鍵(key)映射(map)到數據應該存放的槽(slot)所在位置的函數。
  • 哈希沖突(hash collision):哈希函數將兩個不同的鍵映射到同一個索引的情況。

這么講真的太太太抽象了,我舉個例子吧



Example1這里面的h函數即為哈希函數,由算法很容易知道為x對5取余數 h(47)明顯為2
Example2中的函數同理

訪問鍵值k

對于一個存儲n個數據的哈希表,則哈希表中為HT[0]~HT[N-1],但我們對于訪問的鍵值為2的槽,只需要使用HT[2]即可

Hash Fuction哈希函數

這個有很多,舉幾個經典的算法

int h1(int x){
  return (x%5);
}

int h2(char* x){
  int i,sum;
  for(sum=0, i=0; x[i] != '\0'; i++)
    sum += (int)x[i];
  return (sum%5);
}

int ELFhash(char*key)
{
    unsigned long h=0;
    while(*key)
    {
        h = (h << 4) + *key++;
        unsigned long g = h & 0xF0000000L;
        if(g)
            h ^= g >> 24;
        h &= ~g;
    }
    return h % MOD;
}

ELFhash這個字符串hash函數中涉及許多位運算,有興趣的可以上網查查,這里就不詳述了。

Hash Collision哈希沖突


顯而易見,哈希沖突就是指不同的鍵值k1,k2在哈希函數h(x)映射下到了相同的slot
自然,有沖突就會有解決方案。

Open Hashing 拉鏈法

名詞解釋:叫拉鏈,是因為哈希沖突后,用鏈表去延展來解決。


這個圖中h(x) = x mod 10 ;是一個哈希函數,可見代入x=91x=1的時候都會到映射到鍵值為1的slot,那么這樣就會引發沖突,在拉鏈法中,用鏈表延展去存儲同鍵值的數據。
優點

  1. 拉鏈法處理沖突簡單,且無堆積現象,即非同義詞決不會發生沖突,因此平均查找長度較短;
  2. 在用拉鏈法構造的散列表中,刪除結點的操作易于實現

缺點
在對鏈表進行存儲空間分配的時候,會降低整個程序的運行速率

Closed Hashing 開地址法 (Open Addressing)

名詞解釋:叫Closed,是因為哈希沖突后,并不會在本身之外開拓新的空間,而是繼續順延下去某個位置來存放,所以是一個密閉的空間,所以叫“Closed”,至于開地址(Open Addressing),這個應該相對于那種通過鏈表來開拓新空間,它是在本身地址上,另外找個位置。所以叫開地址。

以下介紹常用的開地址法

  1. Bucket Hashing哈希桶
  2. Probing 探測
Bucket Hashing 哈希桶

這一頁PPT應該很好理解,采用的是哈希桶(Bucket Hashing),每個桶的大小為2,一共有5個桶,所以一共有5*2=10個槽(slot)
插入的算法很簡單

  1. 把數據放到經過哈希函數后得到key值第一個slot里
  2. 若slot已經被占用,用下一個slot
  3. 如果bucket滿了,把數據放到overflow里面

查找算法也很簡單

  1. 先得到鍵值key
  2. 再在bucket中找第一個第二個
  3. 若找不到再在overflow中找
Probing探測

p(k,i)探測函數。其值為第i次探測時相對h(k)的便宜

Pos(i)=(h(k) + p(k ,i)) % M;


Linear Probing 線性探測

p(i) = i ;
p(i) = i * c ;

注意這里的c必須與表的大小M互質

但是線性探測有一個很明顯的缺點,就是數據很可能會聚集在一塊
Quadratic Probing 平方探測


例子

p(1)=1;
p(2)=4;
p(2)=9;
對于h(k1)=3
h(k1)+p(1)=h(k1)+1=4
h(k1)+p(2)=h(k1)+4=7
h(k1)+p(3)=h(k1)+9=12

Random Probing 隨機探測

p(k,i) = random();

但是并不存在真隨機,如果存在真隨機,會出現slot無法被哈希函數搜索到
Pseudo-Random Probing 偽隨機探測


看圖中的
探測序列為r1,r2,r3...即

p(1)=r1;
p(2)=r2;
p(2)=r3;
對于h(k1)=30
h(k1)+p(1)=h(k1)+2=32
h(k1)+p(2)=h(k1)+5=35
h(k1)+p(3)=h(k1)+32=62

Double Hashing 雙重散列
這是用于開放尋址法的最好方法之一,具有隨機選擇排列的許多特性



h2(k)的值必須要與表的大小M互質

刪除

  1. Tombstones墓碑
  2. Local Reorganization
  3. Rehash

where $\mu$ is the mean value, $\sigma^2$ is standard deviation

參考

  • 百度百科
  • 哈希表概述
  • Open Hash
  • 算法導論第三版
  • 華工計算機科學與工程學院數據結構課程PPT
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容