雜湊技術是在記錄的儲存位置和它的關鍵字之間建立乙個確定的對應關係f,使得每個關鍵字key對應 乙個儲存位置f(key),即儲存位置=f(關鍵字)。我們把這種對應關係f稱為雜湊函式,又稱為雜湊(hash)函式。
採用雜湊技術將記錄儲存在一塊連續的儲存空間中,這塊連續儲存空間稱為雜湊表或雜湊表(hash table)。關鍵字對應的記錄儲存位置我們稱為雜湊位址。
(1)在儲存時,通過雜湊函式計算記錄的雜湊位址,並按此雜湊位址儲存該記錄。
(2)當查詢記錄時,我們通過同樣的雜湊函式計算記錄的雜湊位址,按此雜湊位址訪問該記錄。
雜湊技術既是一種儲存方法,也是一種查詢方法。雜湊主要是面向查詢的才儲存結構。雜湊技術最適合的求解問題是查詢與給定值相等的記錄。
倆個關鍵字 key1!=key2,但是卻有f(key1)=f(key2),這種現象我們稱為衝突(collision),並把key1和key2稱為這個雜湊函式的同義詞(synonym)。
1.計算簡單;
2.雜湊位址分布均勻。
取關鍵字的某個線性函式值為雜湊位址,即f(key)=a*key+b(a,b為常數)
優點:簡單,均勻,不會產生衝突。
缺點:需要事先知道關鍵字的分布情況,適合查詢表較小且連續的情況。
若我們用手機號儲存公司員工登記表,那麼我們選擇後面的四位成為雜湊位址就是不錯的選擇。如果還是容易出現衝突問題,可以對抽取出來的數字在進行反轉,右環位移,左環位移,甚至前倆數與後倆數疊加等方法。
抽取方法是使用關鍵字的一部分來計算雜湊儲存的方法,這在雜湊函式中是常常用到的手段。
資料分析法通常適合處理關鍵字位數比較大的情況,如果事先知道關鍵字的分布且關鍵字的若干位分布較均勻,就可以考慮用這個方法。
假設關鍵字1234,那麼平方就是1522756,再抽取中間的3位就是226,用做雜湊位址。再比如關鍵字是4321,那麼它的平方就是18671041,抽取中間的3位就可以是671,也可以是710,用做雜湊位址。
平方取中法比較適合於不知道關鍵字的分布,而位數又不是很大的情況。
摺疊法是將關鍵字從左到右分割成位數相等的幾部分(注意最後一部分位數不夠時可以短些),然後將這幾部分疊加求和,並按雜湊表表長,取後幾位作為雜湊位址。
如關鍵字是9876543210,雜湊表表長為三位,將其分為四組,987|654|321|0,然後將它們疊加求和987+654+321+0=1962,再求後3位得到雜湊位址為926.
摺疊法事先不需要知道關鍵字的分布,適合關鍵字位數較多的情況。
此方法為最常用的構造雜湊函式方法。對於雜湊表長為m的雜湊函式公式為:f(key)=key mod p (p<=m)。
mod是取模(求餘數)的意思。事實上,這方法不僅可以對關鍵字直接取模,也可在摺疊,平方取中後再取模。
本方法的關鍵就在於選擇合適的p,p如果選得不好,就可能容易產生同義詞。
因此根據前輩們的經驗,若雜湊表表長為m,通常p 為小於或等於表長(最好接近m)的最小質數或不包含小於20質因子的合數。
選擇乙個隨機數,取關鍵字的隨機函式值為它的雜湊位址。即f(key)=random(key)。這裡random是隨機函式。
當關鍵字的長度不等時,採用這個方法構造雜湊函式是比較合適的。
1.計算雜湊位址所需的時間;
2.關鍵字的長度;
3.雜湊表的大小;
4.關鍵字的分布情況;
5.記錄查詢的頻率。
當本來都不是同義詞卻需要爭奪乙個位址的情況,我們稱這種現象為堆積。
它的公式是:
它的公式是:
它的公式是:
這裡的隨機數其實是偽隨機數。
對於我們的雜湊表來說,我們事先準備多個雜湊函式。
這裡的rhi就是不同的雜湊函式,可以把前面的什麼除留餘數,摺疊,平方取中全部用上。每當發生雜湊位址衝突時,就換乙個雜湊函式計算。這個方法能夠使得關鍵字不產生聚集,當然,相應地也增加了計算的時間。
將所有關鍵字為同義詞的記錄儲存在乙個單鏈表中,我們稱這種表為同義詞子表,在雜湊表中只儲存所有同義詞表的頭指標。
如:關鍵字集合,用前面同樣的12為除數,進行除留餘數法,可得如圖結構:
鏈位址法對於可能會造成很多衝突的雜湊函式來說,提供了絕不會出現找不到位址的保障。當然,這也就帶來了查詢時需要遍歷單鏈表的效能損耗。
為所有衝突的關鍵字建立乙個公共的溢位區來存放。
就前乙個例子而言,將衝突的關鍵字儲存到溢位表中,如圖:
如果相對基本表而言,有衝突的資料很少的情況下,公共溢位區的結構對查詢效能來說還是非常高的。
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#include "stdafx.h"
#include#define ok 1
#define error 0
#define true 1
#define false 0
#define maxsize 100 /* 儲存空間初始分配量 */
#define success 1
#define unsuccess 0
#define hashsize 12 /* 定義雜湊表長為陣列的長度 */
#define nullkey -32768
typedef int status; /* status是函式的型別,其值是函式結果狀態**,如ok等 */
typedef struct
hashtable;
int m = 0; /* 雜湊表表長,全域性變數 */
/* 初始化雜湊表 */
status inithashtable(hashtable *h)
/* 雜湊函式 */
int hash(int key)
/* 插入關鍵字進雜湊表 */
void inserthash(hashtable *h, int key)
h->elem[addr] = key; /* 直到有空位後插入關鍵字 */
}/* 雜湊表查詢關鍵字 */
status searchhash(hashtable h, int key, int *addr)
return success;
}int main()
; int i, p, key, result;
hashtable h;
key = 39;
inithashtable(&h);
for (i = 0; i1.雜湊函式是否均勻
2.處理衝突的方法
3.雜湊表的裝填因子
裝填因子=填入表中的記錄個數/雜湊表長度;裝填因子標誌雜湊表的裝滿程度。當填入表中的記錄越多,裝填因子越大,產生衝突的可能性越大。
資料結構之查詢 七 雜湊表 雜湊表
基本概念 如何查詢?以上兩例為例,若查詢2001011810216的資訊,可直接訪問v 16 查詢key 9,則訪問h 9 9號位址,若內容為9則成功,若查不到,則返回空指標或空記錄。優缺點 構造方法 制定乙個好的解決衝突的方案 構造雜湊函式需考慮的因素 根據元素集合的特性構造 要求2 無論用什麼方...
資料結構(七) 查詢之雜湊表
雜湊函式的構造原則 將關鍵字分割成位數相同的幾段,最後一位可以 不同。段的長度取決於雜湊表的位址位數,然後 將各段的疊加和 捨去進製 作為雜湊位址 設桶數b,取質數 m b hash key key m 設定雜湊函式為 h key random key 其中,random 為偽隨機函式 開放位址法 ...
資料結構之雜湊表查詢 雜湊表
這個知識點不難,話不多說,直接上 如下 1 include stdafx.h 2 include3 define success 1 4 define unsuccess 0 5 define hashsize 12 定義雜湊表長為陣列的長度 6 define nullkey 3276878 usi...