hash table 雜湊表(雜湊表)

2021-08-07 11:34:25 字數 3522 閱讀 9087

hash table ,也叫雜湊表。涉及到雜湊函式、雜湊衝突處理的問題。雜湊函式是雜湊表的關鍵,是用來從值到雜湊表索引(存放位置)的對映。

比如:要存放乙個學校學生的姓名,他們是amanda, jack, andy, tom, bob, black等等500個人。我們可以設計乙個雜湊表,容量為500,來存放這些學生的資訊。雜湊表的目的是快速訪問,利用陣列的隨機訪問性,快速的通過下表訪問元素。需要設計乙個雜湊函式,來決定每個人存在什麼地方。比如有乙個雜湊函式:

h(name) = {

return name[0] -'a'

這個函式會按照首字母序把資訊放在對應位置。但是andy和amanda會造成衝突,因為乙個位置上不能存兩個人,amanda去存時發現andy已經占用了這個位置,此時就需要衝突處理。

雜湊法儲存的思想是由關鍵字值和hash函式決定資料的儲存位址。雜湊表是單向的,即通過key獲得hash值,可以得到儲存位址,而反過來知道hash,無法算得key。

例如,最多有31個不重複的0~999之間的數字需要存放,此時可以用乙個31容量的陣列儲存這些數字,並且使用乙個hash 函式:

h(i) = n mod 31 

將這些0~999的數字對映到0~30。但是會存在雜湊衝突的問題。比如95和64對映的結果都是2,此時就需要解決雜湊衝突了。

1、直接定址法

直接定址法的雜湊函式是關鍵碼的線性函式,即: h(key)=a*key+b (a,b為常數)。

2、除留餘數法

除留餘數法的基本思想是:選擇某個適當的正整數p,以關鍵碼除以p的餘數作為雜湊位址,即h(key)=key mod p,其中雜湊表的大小最好是質數,即p是質數。

3、數字分析法

數字分析法根據關鍵碼在各個位上的分布情況,選取分布比較均勻的若干位組成雜湊位址。

4、平方取中法

平方取中法是對關鍵碼平方後,按雜湊表大小,取中間的若干位作為雜湊位址。

5、摺疊法

摺疊法是將關鍵碼從左到右分割成位數相等的幾部分,最後一部分位數可以短些,然後將這幾部分疊加求和,並按雜湊表表長,取後幾位作為雜湊位址。通常有兩種疊加方法:

衝突處理策略有三類:

注意:還有兩種說法

開雜湊表-------鏈式位址法

閉雜湊表-------開放位址法

開哈與閉雜湊區別:

開雜湊只會和相同值發生衝突,而閉雜湊除了與相同值發生衝突,還會與不同值發生衝突

所以,開雜湊不受密度影響,而閉雜湊受密度影響

比如訪問31不重複的個0~999的數字,不在只使用31容量,而是擴大到999個,如此以來肯定不會衝突,每乙個數字都占有乙個位,訪問也非常快速。缺點是浪費了大量的空間。一般情況下,雜湊表容量是需儲存專案的1.5~2倍,可以一定程度上減少衝突次數,但是無法消除。

用開放定址法處理衝突得到的雜湊(雜湊)表叫做閉雜湊表。開放定址法的關鍵在於生成乙個探測序列,存放和訪問都基於這個序列。四種開放定址方法的區別就是如何選擇這個序列。

開放定址有四種方法:線性探測、二次探測、雙雜湊、隨機探測。這四種方法的缺點(或者說不足),就是都採用了「拆東牆補西牆」的「搶劫peter來滿足paul」的方法,一旦占用了別人的儲存空間,那個位置本來的擁有者就必須進行探測,而無法使用雜湊函式直接讀取,浪費了時間。所以,開放定址方法會造成連鎖反應。更好的方法是建鏈

以下的 i 都是經過雜湊函式對映後的位置。

(1) 線性探測

公式:h

i=(h(key)+d

i)%m(di

=1,2,3,4,...,m-1)  m 為閉雜湊表的長度。

序列: i+1, i+2, i+3, i+4 ... 

不允許從雜湊表刪除元素的前提下,一旦發生衝突,就從衝突位置開始環形地遍歷雜湊表,直到找到乙個空位。查詢時,先根據雜湊函式找到對應位置

1. 如果是空,則表明元素不在雜湊表中

2. 如果非空,且元素與目標元素匹配,則找到

3. 如果非空,但元素與目標元素不匹配,則從當前位置開始遍歷,直到找到元素,或碰到空位或返回到這個位置表明沒有此元素。

如果允許刪除元素,則需要標記被刪除的位置為「曾經被占用過」,否則在執行上述步驟時會出錯。

缺點:會造成首次堆積問題。查詢越來越浪費時間,因為衝突的話,要去遍歷雜湊表。

線性探測法使得大量元素在相鄰位址出現「聚集」現象,降低效率。主要是解決衝突演算法選擇不好,如果選擇平方探測法,則可以避免堆積問題!

(2) 二次探測法

公式:h

i=(h(key)+d

i)%m (di=1

2,-12,2

2,-2

2,…,q

2,-q2)

序列:i+1^2, i-1^2, i+2^2, i-2^2, i+3^2, i-3^2 ... 

按照二次序列,找到乙個合適的空位,存放數值

缺點:避免了首次堆積,但會造成二次堆積。

(3) 雙雜湊法

公式:h = (h(key) + d) % m(d = h2(key), 2*h2(key), 3*h2(key) ...) 

序列:i+hash2(x), i+2*hash2(x), i+3*hash2(x)

引入了第二個雜湊函式,使用新的檢測序列,保證擁有相同hash值的元素擁有不同的探測序列。

(4) 隨機探測法

公式:h = (h(key) + d) % m(d = 乙個隨機值)

建鏈法是stl中hash_map使用的方法。當存放位置衝突時,建起乙個單鏈,存放這些衝突的元素(被稱為同義詞),訪問時遍歷這條鏈,知道找到或到達鏈尾。

非同義詞決不會發生衝突,因此平均查詢長度較短

與開放定址法相比,拉鍊法有如下幾個優點:

(1)拉鍊法處理衝突簡單,且無堆積現象,即非同義詞決不會發生衝突,因此平均查詢長度較短;

(2)由於拉鍊法中各煉表上的結點空間是動態申請的,故它更適合於造表前無法確定表長的情況;

(3)開放定址法為減少衝突,要求裝填因子α較小,故當結點規模較大時會浪費很多空間。而拉鍊法中可取α≥1,且結點較大時,拉鍊法中增加的指標域可忽略不計,因此節省空間;

(4)在用拉鍊法構造的雜湊表中,刪除結點的操作易於實現。只要簡單地刪去鍊錶上相應的結點即可。而對開放位址法構造的雜湊表,刪除結點不能簡單地將被刪結點的空間置為空,否則將截斷在它之後填人雜湊表的同義詞結點的查詢路徑。這是因為各種開放位址法中,空位址單元(即開放位址)都是查詢失敗的條件。因此在用開放位址法處理衝突的雜湊表上執行刪除操作,只能在被刪結點上做刪除標記,而不能真正刪除結點。

3、解釋下啥是裝填因子

HashTable 雜湊表(雜湊表)

雜湊表 雜湊表 是根據關鍵字 key 而訪問在記憶體位置的資料結構。其方法是 它通過乙個關鍵值的函式將所需的資料對映到表中的位置來訪問資料,這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表 雜湊表 構造雜湊表的幾種方法 直接定址法 取關鍵字的某個線性函式為雜湊位址,hash key key 或 h...

HashTable雜湊表 雜湊表(雜湊桶)

處理雜湊衝突的開鏈法 拉鍊法 雜湊桶 使用素數做雜湊表的長度,可以降低雜湊衝突 素數表size t getnextprime size t num 素數表 雜湊桶的節點的定義 template struct hashnode 在插入前檢查容量,以及負載因子。不夠就進行增容,按素數表進行增,以減小雜湊...

雜湊表(雜湊)HashTable實現

近期刷leetcode發現凡是找字串中反覆字元或者陣列中找反覆資料的時候就不知道從何下手了。所以決定學習一下雜湊表解題。雜湊表的原理主要是解決分類問題,hash表是介於鍊錶和二叉樹之間的一種中間結構。鍊錶使用十分方便,可是資料查詢十分麻煩 二叉樹中的資料嚴格有序,可是這是以多乙個指標作為代價的結果。...