標籤:void 資料結構 這一 ext for line 選擇 find margin
雜湊表
雜湊表是根據設定的雜湊函數H(key)和處理衝突方法將一組關鍵字映射到一個有限的地址區間上,並以關鍵字在地址區間中的象作為記錄在表中的儲存位置,這種表稱為雜湊表或散列,所得儲存位置稱為雜湊地址或散列地址。作為線性資料結構與表格和隊列等相比,雜湊表無疑是尋找速度比較快的一種。
對不同的關鍵字可能得到同一散列地址,即k1≠k2,而f(k1)=f(k2),這種現象稱為碰撞(英語:Collision)。具有相同函數值的關鍵字對該散列函數來說稱做同義字。綜上所述,根據散列函數f(k)和處理碰撞的方法將一組關鍵字映射到一個有限的連續的地址集(區間)上,並以關鍵字在地址集中的“像”作為記錄在表中的儲存位置,這種表便稱為散列表,這一映射過程稱為散列造表或散列,所得的儲存位置稱散列地址。
尋找:
1. 直接定址法:取關鍵字或關鍵字的某個線性函數值為散列地址。即H(key)=key或H(key) = a·key + b,其中a和b為常數(這種散列函數叫做自身函數)。若其中H(key)中已經有值 了,就往下一個找,直到H(key)中沒有值了,就放進去。2. 數字分析法:分析一組資料,比如一組員工的出生年月日,這時我們發現出生年月日的前幾位元字大體相同,這樣的話,出現衝突的幾率就會很大,但是我們發現年月日的後幾位表示 月份和具體日期的數字差別很大,如果用後面的數字來構成散列地址,則衝突的幾率會明顯降低。因此數字分析法就是找出數位規律,儘可能利用這些資料來構造衝突幾率較低的散列 地址。3. 平方取中法:當無法確定關鍵字中哪幾位分布較均勻時,可以先求出關鍵字的平方值,然後按需要取平方值的中間幾位作為雜湊地址。這是因為:平方後中間幾位和關鍵字中每一位都 相關,故不同關鍵字會以較高的機率產生不同的雜湊地址。4. 摺疊法:將關鍵字分割成位元相同的幾部分,最後一部分位元可以不同,然後取這幾部分的疊加和(去除進位)作為散列地址。數位疊加可以有移位疊加和間界疊加兩種方法。移位疊 加是將分割後的每一部分的最低位對齊,然後相加;間界疊加是從一端向另一端沿分割界來回摺疊,然後對齊相加。5. 隨機數法:選擇一隨機函數,取關鍵字的隨機值作為散列地址,通常用於關鍵字長度不同的場合。6. 除留餘數法:取關鍵字被某個不大於散列表表長m的數p除後所得的餘數為散列地址。即 H(key) = key MOD p,p<=m。不僅可以對關鍵字直接模數,也可在摺疊、平方取中等運算之 後模數。對p的選擇很重要,一般取素數或m,若p選的不好,容易產生同義字。 輸入n,輸入數列An,再輸入m個數查詢是否在An內,在輸出“YES”,否這輸出“NO”。
1 #include<cstdio> 2 #define M 4194303 3 int n,m,ans,cnt; 4 int s[50005]; 5 int hashline[M+1]; 6 int next[12600005];//鏈 7 int fline[12600005];//鏈上值 8 9 void insert (int x){//插入 10 int key=x%M;11 fline[++cnt]=x;12 next[cnt]=hashline[key];13 hashline[key]=cnt;14 }15 16 bool find (int c){//查詢 17 int key=c%M;18 for(int i=hashline[key];i;i=next[i])19 if(c==fline[i])return true;20 return false;21 }22 23 int main(){24 scanf("%d%d",&n,&m);25 for(int i=1;i<=n;++i){26 scanf("%d",&s[i]);27 insert(s[i]);28 }29 for(int i=1;i<=n;++i){30 int c;31 scanf("%d",&c);32 if(find(c))printf("YES\n");33 else printf("NO\n");34 }35 return 0;36 }
為減少衝撞,選好大質數M非常重要。
M={1000000007,1998585857,4194303}
#雜湊# ----- 雜湊表初學