數據結構與算法-哈希表

哈希表定義:

根據設定的哈希函數H(key)和處理沖突的方法將一組關鍵字映像到一個有限的連續的地址集(區間)上,并以關鍵字在地址集中的“像”作為記錄在表中的位置,這種表便稱為哈希表,這一映像過程稱為哈希造表或散列,所得到存儲位置稱哈希地址或散列地址。


前言

在順序查找、二分查找、斐波那契查找、插值查找、最優(次優)查找樹、二叉排序樹、二叉平衡樹、B-樹等查找方法中,記錄的位置相對是隨機的,在查找記錄時依賴與關鍵字的比較(有><=三種情況)。因此以上查找的效率依賴查找過程中進行比較的次數。
若能將所查記錄與其存儲位置建立一個對應關系f,使每個記錄中關鍵字與其存儲位置一一對應,則在查找時只需查看在其對應存儲位置有無包含所查關鍵字的記錄即可。
我們稱上述對應關系f為“哈希(Hash)函數”。按照這個思想建立的表為哈希表。
對于不同關鍵字可能得到相同的哈希地址,即key1!=key2,而f(key1)==f(key2),這種現象成為沖突(collision)。具有相同哈希值的關鍵字稱為同義詞(synonym)。在一般情況下,沖突只能盡可能的減少而不能完全避免(哈希函數是一個壓縮映像)。因此在建造哈希表時,不僅要設定一個“好”的哈希函數,而且要設定一種處理沖突的辦法。


哈希函數構造方法

1、直接定址法

取關鍵字或關鍵字的某個線性函數值作為哈希地址。即H(key)=key或者H(key)=a×key+b。
直接定址法所得的地址集與關鍵字集合大小相同,不同關鍵字不會產生沖突。

2、數字分析法

假設關鍵字都是事先知道的,則可取關鍵字的若干數位組成哈希地址。

3、平方取中法

取關鍵字平方后的中間幾位作為哈希地址。一個數平方后的中間幾位數和數的每一位都相關,由此隨機分布的關鍵字得到的哈希地址也是隨機的,取的位數由表長決定。

4、折疊法

將關鍵字分割成位數相同的幾部分(最后一部分位數也可以不同),然后取這幾部分的疊加和(舍去進位)作為哈希地址。
關鍵字位數很多,而且關鍵字的每一位上數字分布大致均勻時可以采用此法。

5、除留余數法

取關鍵字被某個不大于哈希表長m的數p除后所得余數為哈希地址。即H(key)=key MOD p,p<=m;
可以對關鍵字直接取模,也可以在折疊,平方運算之后取模。
但是,在使用此法時,對p的選擇很重要。若p選的不好,容易產生同義詞。
一般情況下,可以選p為質數或不包含小于20的質因子的合數。
6、隨機數法
選擇一個隨機函數,取關鍵字的隨機函數值作為它的哈希地址,即H(key)=Random(key)。通常,關鍵字長度不等時采用此法構造哈希函數較為恰當。


處理沖突的方法

1、開放定址法

Hi=(H(key)+di) MOD m,i=1,2,3,...,k(k<=m-1)
其中:H(key)為哈希函數;m為哈希表表長;di為增量序列有三種取法:di=1,2,3,...,m-1,稱線性探測再散列;di=12,-12,22,-22,...,+-k2,(k<=m/2)稱二次探測再散列;di=偽隨機數序列,稱偽隨機探測再散列。

2、再哈希法

Hi=RH(key) i=1,2,3,...,k

3、鏈地址法

將所有關鍵字同義詞存儲在同一線性鏈表中。

4、建立公共溢出區

哈希表的查找及其分析

在哈希表上查找過程和建造哈希表過程基本一致。若查找位置上沒有記錄則查找不成功,否則比較關鍵字,若和給定值相等,則查找成功,否則根據建表時設定的處理沖突的方法找“下一地址”,直至哈希表某個位置為“空”或者表中所填記錄關鍵字等于給定值時為止。

int hashsize[]={997,...}; //哈希表容量遞增表,一個合適的素數序列。
typedef struct{
    ElemType *elem;
    int count;
    int sizeindex;
}HashTable;

\#define SUCCESS 1
\#define USUCCESS 0
\#define DUPLICATE -1
Status SearchHash(HashTable H,KeyType K,int &p,int &c){
    //若查找成功返回SUCCESS,p指示待查元素在表中的位置,否則返回UNSUCCESS,p指示插入位置。
    //c用來記錄沖突次數

  p=Hash(K);
  while(H.elem[p].key!=NULLKEY&&!EQ(K,H.elem[p].key)
      collision(p,++c);
  if EQ(K,H.elem[p].key)
      return SUCCESS;
  else return UNSUCCESS;
}//SearchHash

Status InsertHash(HashTable &H,Elemtype e){
  c=0;
  if(SearchTable(H,e.key,p,c))
      return DUPLICATE;
  else if(c<hashsize[H.sizeindex]/2){
      H.elem[p]=e;
      ++H.count;
      return OK;
  }
  else{RecreateHashTable(H); return UNSUCCESS;}
}//InsertHash

由于沖突的產生,使得哈希表的查找過程仍然是一個給定值和關鍵字比較的過程。因此要以平局查找長度為衡量哈希表查找效率的度量。

在查找過程中需和關鍵字比較的個數取決于
1.哈希函數
2.處理沖突的方法
3.哈希表的裝填因子

在線性探測再序列中易產生記錄的二次聚集,即對于哈希地址不同的 關鍵字產生沖突;鏈地址法則不會產生類似情況。

裝填因子越大表示哈希表的裝滿程度,裝填因子越小,發生沖突的概率越小,平均查找長度越小。

哈希表的平均查找長度是裝填因子的函數,而不是表長n的函數,可以選擇一個合適的裝填因子使平均查找長度限定在一個范圍內。而對于非鏈地址處理沖突的哈希表中刪除一個記錄,需在該記錄位置填一個特殊符號,以免找不到在它之后填入的同義詞。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念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