雜湊(hash)同順序、鏈結和索引一樣,是儲存集合的又一種方法。
不同的是,雜湊表(雜湊表)在元素的儲存位置和它的關鍵字之間建立了乙個對應關係。
雜湊儲存的基本思想是:以每個元素的關鍵字k為自變數,通過乙個函式(稱為雜湊函式或雜湊函式)計算出函式值,把這個值(雜湊位址或雜湊位址)解釋為一塊連續儲存空間(即陣列空間)的單元位址(即下標),將該元素儲存到這個單元中。使用的陣列空間是線性表進行雜湊儲存的位址空間,所以被稱之為雜湊表或雜湊表(hash list或hash table)。
雜湊函式是乙個映像,因此雜湊函式的設定很靈活,只要使得任何關鍵字由此所得的雜湊函式值都落在表長允許範圍內即可。
對不同的關鍵字可能得到同乙個雜湊位址,這種現象稱為衝突(
collision),具有相同函式值的關鍵字對該雜湊函式來說稱作同義詞(synonym)。
衝突很難避免,但發生衝突的可能性卻有大有小,這主要與三個因素有關:
1.裝填因子(已存入的元素數與雜湊表空間大小的比值),該值越小,衝突的可能性就越小,但儲存空間的利用率就越低,一般這個值控制在0.6~0.9範圍內為宜(why?)。
2.雜湊函式的選擇,若選得好,就可以使雜湊位址盡可能均勻地分布在雜湊空間上。
3.解決衝突的方法,解決衝突的方法也會影響衝突發生的可能性。
雜湊儲存的兩個關鍵問題就是:1.如何構造雜湊函式盡量避免衝突和2.衝突發生後如何解決。
構造雜湊函式的目標是使雜湊位址能夠盡可能均勻地分布在雜湊空間上,同時使計算盡可能簡單。
通常考慮的因素有:計算雜湊函式所需時間;關鍵字長度;雜湊表的大小;關鍵字的分布情況;記錄的查詢頻率。
常用的構造雜湊函式的方法有:
取關鍵字或關鍵字的某個線性函式值為雜湊位址。
h(key)=key或h(key)=a*key+b
其中a和b為常數,這種雜湊函式叫做自身函式。
這種函式對於不同的關鍵字不會發生衝突。
取關鍵字中某些取值較分散的若干數字位組成雜湊位址。
適合於所有關鍵字已知,且對每一位的取值做出了一定分析。
取關鍵字平方後的中間幾位作為雜湊位址。
因為乙個數平方後的中間幾位數和數的每一位都相關,使得雜湊位址具有較好的分散性,具體取的位數由表長決定。
平方取中法適用於關鍵字中的每一位取值都不夠分散或者較分散的位數小於雜湊位址所需要的位數的情況。
將關鍵字分割成位數相同的幾部分(最後一部分的位數可以不同),然後取這幾部分的疊加和(捨去進製)作為雜湊位址,這種方法稱為摺疊法(folding)。
數字疊加時可以有移位疊加和間界疊加(就是把相鄰的數映象疊加)兩種方法。
摺疊法適用於關鍵字的位數較多,而且關鍵字中每一位上數字分布大致均勻的情況。
取關鍵字被某個不大於雜湊表表長m的數p除后所得的餘數為雜湊位址。
h(key)=k%p
(這裡有個疑團啊,嚴蔚敏的《資料結構》這本書裡是如上這麼寫的,說p必須小於m,但是另一本書:徐孝凱《資料結構實用教程》裡說p應該大於m,並且應該取1.1m~1.7m之間的乙個素數。我是這麼想的,是不是按後一種取法就可以完全避免衝突了,而前一種取法是想著把衝突留在後面再解決。)
這是一種最常用的構造雜湊函式的方法。它不僅可以對關鍵字直接取模,也可以在摺疊、平方取中等運算之後取模。
選擇乙個隨機函式,取關鍵字的隨機函式值作為它的雜湊位址。
h(key)=random(key)
其中random為隨機函式。
通常,當關鍵字長度不等時採用此法。
若由某個關鍵字得到的雜湊位址的位置上已經存在別的記錄,則發生衝突,需要為該關鍵字的記錄找到另乙個「空」的雜湊位址。
在處理衝突的過程中可能得到乙個位址序列,若再次得到的雜湊位址仍然發生衝突就再求下乙個位址,依次類推,直到不發生衝突為止,此時找到的位址為記錄在表中的位址。
通常處理衝突的方法有下列幾種:
開放定址法就是從發生衝突的那個單元開始,按照一定的次序,從雜湊表中查詢出乙個空閒儲存單元的方法。在這種方法中,雜湊表的空閒單元不僅向雜湊位址為對應值的同義詞元素開放,而且向發生衝突的其他元素(非同義詞元素)開放,此方法的名稱由此而來。
從發生衝突的單元起進行查詢有多種方法,每一種都對應一定的查詢次序或查詢路徑,產生乙個確定的探查序列(即待比較元素的位址序列)。
hi=(h(key)+di)%m i=1,2,...,k k<=m-1
其中: 為雜湊函式;m為雜湊表長; 為增量序列,可以有下列取法:
(1)線性探測再雜湊(線性探查法)
di=1,2,3,…,m-1
線性探測再雜湊可以保證做到:只要雜湊表未填滿,總能找到乙個不發生衝突的位址。
但是線性探查容易造成堆積現象,因為探查序列過分集中在發生衝突的單元後面,沒有在整個雜湊空間上分散開。
(2)二次探測再雜湊(平方探查法)
di=12,-12,22,-22,32,…
(另一種說法是不需要負號的部分)。
(3)偽隨機探測再雜湊
di=偽隨機數序列
在處理衝突的過程中有可能會出現兩個第乙個雜湊位址不同的記錄爭奪同乙個後繼雜湊位址的現象,即在處理同義詞的衝突過程中又新增了非同義詞的衝突,這種現象稱為「二次聚集」,對查詢不利。
hi=rhi(key)
rhi是各自不同的i個雜湊函式,即在同義詞產生位址衝突時計算另乙個雜湊函式位址,直到衝突不再發生。這種方法不易產生聚集,但增加了計算的時間。
將所有關鍵字為同義詞的記錄儲存在同一線性鍊錶中。
chain chainhash[m]
其每個分量的初始狀態都是空指標。凡雜湊位址為i的記錄都插入到頭指標為chainhash[i]的鍊錶中。在鍊錶中的插入位置可以在表頭或表尾;也可以在中間,以保持同一線性鍊錶中按關鍵字有序。
假設雜湊函式的值域為[0,m-1],則設向量hashtable[0…m-1]為基本表,每個分量存放乙個記錄,另設立向量overtable[0…v]為溢位表。所有關鍵字和基本表中關鍵字為同義詞的記錄,不管它們由雜湊函式得到的雜湊位址是什麼,一旦發生衝突,都填入溢位表。
在雜湊表上進行查詢的過程和雜湊造表的過程基本一致。
給定k值,根據造表時設定的雜湊函式求得雜湊位址,若表中此位置上沒有記錄,則查詢不成功;
若有記錄,則比較關鍵字,若和給定值相同,則查詢成功;若關鍵字不同,則根據造表時設定的處理衝突的方法找「下一位址」,直至雜湊表中某個位置為「空」或者表中所填記錄的關鍵字等於給定值時為止。
值得提醒的是,若要在非鏈位址處理衝突的雜湊表中刪除乙個記錄,則需在該記錄的位置上填入乙個特殊的符號,以免找不到在它之後填入的「同義詞」的記錄。
查詢演算法 雜湊演算法,雜湊表查詢
那麼問題來了,如果集合s中同時存在值k 16和值k 27,我們該如何將兩個位址一樣的值存入雜湊表呢?常用的雜湊函式 處理衝突的方法 2.連位址法 雜湊表涉及的是一種對映關係,可以根據某個值查詢到關鍵字的位址,這樣的做法省去了比較的時間,優化了演算法。雜湊表是把值 關鍵字 存到跟它具有 唯一 對映的格...
查詢 雜湊表查詢(雜湊表)
1 雜湊表查詢定義 雜湊技術是在記錄的儲存位置和它的關鍵字之間建立乙個確定的對應關係f,使得每個關鍵字key對應乙個儲存位置f key 查詢時,根據這個確定的對應關係找到給定值key的對映f key 若查詢集合中存在這個記錄,則必定在f key 的位置上。採用雜湊技術將記錄儲存在一塊連續的儲存空間中...
演算法 查詢 雜湊表查詢
查詢除了線性表的查詢 順序 二分 分塊 樹上查詢 bst b 樹 還有一種雜湊查詢。相比於前兩種查詢,雜湊表的查詢效率驚人的高o 1 它採用的直接定址技術,基本上就是實現了精準打擊,達到一擊而中的效果。所謂的直接定址技術,說白了,就是儲存記錄時,通過雜湊函式計算出乙個雜湊位址 讀取記錄時,通過同樣的...