380 likes | 932 Views
資料結構 第九章:雜湊法( Hash ). 鄧姚文 ywdeng@mail.knu.edu.tw http://w3.im.knu.edu.tw/~joseph/. 雜湊法. 認識雜湊法 常見的雜湊函數 碰撞問題. h(k). k:key. r:index. 鍵值 識別字. 索引值 儲存位置. Hash function 雜湊函數. 雜湊法( Hashing ). 理想狀況: O(1) 搜尋 用途 加速搜尋速度 使用較小的陣列處理廣大人口的資料 加密 實際情形: 碰撞( Collision ):兩個鍵值對應到同一個位置
E N D
資料結構第九章:雜湊法(Hash) 鄧姚文 ywdeng@mail.knu.edu.tw http://w3.im.knu.edu.tw/~joseph/
雜湊法 • 認識雜湊法 • 常見的雜湊函數 • 碰撞問題
h(k) k:key r:index 鍵值 識別字 索引值 儲存位置 Hash function 雜湊函數 雜湊法(Hashing) • 理想狀況: • O(1) 搜尋 • 用途 • 加速搜尋速度 • 使用較小的陣列處理廣大人口的資料 • 加密 • 實際情形: • 碰撞(Collision):兩個鍵值對應到同一個位置 • 最壞的情況:退化成 O(N) 搜尋
雜湊法的定義 • Hash function h(x) • 將鍵值轉換成位址 • Hash table(雜湊表) • Bucket(桶) • 雜湊表之中的一個儲存位置 • Home bucket • 在 h(x) 位置的 Bucket • Slot(槽) • 在一個Bucket之中再切割出來的儲存格
Hashtable 0 1 2 3 4 5 slots buckets 專有名詞:雜湊表(Hash Table)
雜湊法專有名詞 • Collision(碰撞) • h(x) = h(y),兩個鍵值對應到同一個 Bucket • 同義字(Synonym) • Overflow(溢位) • Bucket 的儲存空間滿了 • 對同一個bucket的collision數量超過slot的數量時 • 載入密度(Loading Factor) • Loading Density 裝載密度 • =N/(SB) i.e.總資料量/(槽數*桶數) • 完美雜湊(perfect hashing) • No collision, no overflow
雜湊法的優點及設計原則 • 使用雜湊法搜尋,資料不需事前經過排序。 • 在沒有碰撞或溢位的情況下,只需一次讀取資料即可找到想要找的資料,且搜尋速度與資料量的大小無關。O(1)。 • 保密性高,若不知道 h(x),就無法取得資料。 • 可做資料壓縮,節省空間。
雜湊函數的設計 • 設計一函數y=f(x), x,y為正整數 • 通常令x>y • 一個好的雜湊函數必須: • 避免碰撞 • 但是:除非事先知道key的分佈狀況,否則碰撞在所難免 • 均勻分佈 • 將鍵值均勻地散佈在 Hash Table 之中 • 容易計算 • Hash Function 的計算時間必須為O(1)
常見的雜湊函數 • 常見的雜湊法有 • 除法(Division) • 中間平方法(Mid-Square) • 折疊法(Folding) • 數位分析法(Digit Analysis)
除法The Division Hash Function • 最簡單的雜湊函數 • 將資料除以某一個常數後,取餘數來當索引。 • 例如在一個有13個位置的陣列中,只使用到7個位址,值分別是12,65,70,99,33,67,51。那我們就可以把陣列內的值除以13,並以其餘數來當索引,我們可以用下例這個式子來表示: h(key) = key % M • 在這個例子中,我們所使用的M=13。
除法 • 優點 • 計算容易 • M 值可以視執行時的情況調整 • 缺點 • 連續的key值必轉換至連續的bucket
除法 public class DivisionMethod { static int M = 1031; //質數 public static int h(int x) { return Math.abs(x) % M; } } M 值以大於 20 的質數為佳!
原始資料:8864, 100, 2, 77, 729 h(x) = x % 11 Hash Table 77 100 2 729 8864 0 1 2 3 4 5 6 7 8 9 10 除法
中間平方法Middle-Square Method • 它是把資料乘以自己,之後再取中間的某段數字做索引。 • 避免使用除法 • 整數除法的計算通常比整數乘法慢 • 事實上所有的整數計算都被迫除以W取餘數,W=2w(w為word size)
public class MiddleSquareMethod { static int k = 10; // M==1024 static int w = 32; public static int h(int x) { return (x * x) >>> (w - k); } } 相當於將接近LSB的 (w-k)個位元除去 >>> 為 arithmetic shift-right 0 中間平方法
5 1 0 3 2 4 X 2 6 0 4 3 0 5 8 4 9 7 6 X2 超過容量,自動遺失 0 0 0 0 5 8 h(X) >>>右移4位 中間平方法
中間平方法 • 優點 • 將連續的key分散投射(Scatter) • 缺點 • 如果鍵值最左邊或最右邊有很多個 0,則效果很差 • 10000, 20000,30000,40000,50000 • Middle-square method only consider a subset of the bits in the middle
折疊法 • 折疊法是將資料轉換成一串數字後,先將這串數字先拆成數個部份,最後再把它們加起來,就可以計算出這個鍵值的Bucket Address。
折疊法的分類 • 移動折疊法 • 直接將每一部份相加所得的值作為其bucket address • 邊界折疊法 • 將每一部份的數字中的奇數位段或偶數位段反轉,再行相加來取得其bucket address
移動折疊法 K A I N A N 原始資料: 75 65 73 78 65 78 ASCII Code: 75 65 73 78 65 78 15 21 2 Bucket Address: 1521
邊界折疊法 1 75 65 2 87 37 偶數位段反轉 3 65 78 28 80 2 Bucket Address: 2880 1 56 57 奇數位段反轉 73 78 2 3 87 56 奇數位段反轉 17 91 2 Bucket Address: 1791
數位分析法 • 數位分析法適用於資料不會更改,且為數字型態的靜態表。 • 在決定雜湊函數時先逐一檢查資料的相對位置及分佈情形,將重複性高的部份刪除。
電話 Bucket Address 電話 07-772-2234 234 07-772-2234 07-772-4525 525 07-772-4525 07-772-2604 604 07-772-2604 07-772-4651 651 07-772-4651 07-772-2285 285 07-772-2285 07-772-2101 101 07-772-2101 07-772-2699 699 07-772-2699 07-772-2694 694 07-772-2694 數位分析法
碰撞問題 • 雜湊函數都是 Many-to-One Mapping • 碰撞必然會發生 • Overflow 怎麼辦?
常見的溢位處理方法 • Linear probing線性探測法 • 往下找一個空位(到底繞回頭) • Rehashing 再雜湊 • 準備多組雜湊函數h1(x),h2(x),h3(x),…,hm(x),用h1(x)發生溢位,則改用h2(x),若再發生溢位則改用h3(x),… • Quadratic probing 平方探測法 • 當 h(x) 溢位,下一次改用 ( h(x) + i2 ) % b 與 ( h(x) – i2 ) % b, 1 i (b-1)/2 • Chaining 鏈結串列 • 用 Linked-List 解決固定大小的陣列發生溢位的問題 • Slot 的數目可動態調整
線性探測法 • Linear open addressing 線性開放位址 • 往後找尋一個空的儲存位置 • 把雜湊的位置視為環狀結構 • 類似的鍵值經會聚集在一起 • Clustering problem • 搜尋時間變長 • 資料刪除時怎麼處理?
原始資料:88, 108, 48, 58, 228, 888 h(x) = x % 10 Hash Table 48 58 228 888 88 108 0 1 2 3 4 5 6 7 8 9 Clustering Problem
Linear Probing 線性探測 • 搜尋: • Start from its home bucket • If it is not in its home bucket, Looking forward (circular) until • Found! • An empty bucket is reached=>element does not exist! • Return to the home bucket=>element does not exist!
平方探測法 • 以平方探測法改善 Clustering Problem • 在平方探測中,當溢位發生時,下一次搜尋的位址是 • (f(x)+i2) % B • (f(x)-i2) % B • 讓資料值加或減 i2
平方探測法尋找過程 • 例如資料值key,雜湊函數f: • 第一次尋找:f(key) • 第二次尋找:(f(key)+12)%B • 第三次尋找:(f(key)-12)%B • 第四次尋找:(f(key)+22)%B • 第五次尋找:(f(key)-22)%B • 第n次尋找:(f(key)±((B-1)/2)2)%B • 其中,B必須為4j+3型的質數,且1≦i≦(B-1)/2
再雜湊 • 再雜湊就是一開始就先設置一系列的雜湊函數,如果使用第一種雜湊函數出現溢位時就改用第二種,如果第二種也出現溢位則改用第三種,一直到沒有發生溢位為止。 • 例如h1為key%8,h2為key*key,h3為key*key%8,h4……。
Rehashing再雜湊 • Use 2 distinct hash functions • h: K{0,1,…,M-1} • h’:K{1,2,…,M-1} • hi(x)=(h(x)+i*h’(x)) mod M
Chaining鏈結串列 • 將雜湊表的所有空間建立n個串列,最初的預設值只有n個串列首。 • 發生溢位時把相同位址之鍵值鍵結在串列首的後面,形成一個鍵結串列,直到所有的可用空間全部用完為止。
0 10 20 NULL 1 NULL 2 32 NULL 3 NULL 4 24 NULL 5 NULL 6 NULL 7 NULL 8 48 NULL 9 NULL Chaining鏈結串列