HASHING
Michael Tsai
2010/12/24
提早下課 !
•
作業五期限延長至週四下午五點•
期末將近 , 請各位同學注意身體健康 ( 該封電動了 )•
補課時間請班代利用提早下課時間調查後通知我•
( 原則上以下周為主 )Outline
•
上次未解決的一些問題•
Sorting on several keys & radix sort•
Static hashing•
Dynamic hashing上次未解決的問題 (1)
• Non-comparison sorting time complexity
• 電話排序問題
• 假設全部電話號碼有 s 個種可能 ( 所有排列組合 )
• 我們有 n 組電話要排
• 則使用超大表格排序法需要 O(s)
• 如果使用 comparison-based sorting 平均需要
• 假設超大表格排序法所需時間為
• 假設 comparison-based 排序法所需時間為
• break even point 為 s= 10 n log n
• 假設以台北市電話號碼為例 ,
• , n<
• break even point 大約為 n=k
• 當 n 大於此數則 non-comparison sorting 比較快
•
上次未解決的問題 (2)
•
問 : 如果我們使用 linked list representation 來做 mer ge sort ( 而不是用 array), 我們還需要另外一個跟 n 一 樣大小的地方來存資料嗎 ?•
答案 : 不需要•
參閱 : http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
•
但是如果原本資料是放在 array, 還是需要一些額外的空 間 ( 做 linked list)Sorting on several keys
• 假設 K 有很多個 sub-key
• 則 iff
• for some , or
• 則我們可以有以下的 sorting 方法 .
• 先依照 most significant key sort, 然後依序往 least significan t key sort 過去 : Most Significant Digit first (MSD) sorting
• 先依照 least significant key sort, 然後依序往 most significan t key sort 過去 : Least Significant Digit first (LSD) sorting
•
6
Most significant key Least significant key
Sorting on several keys
•
哪一種比較好 ?•
如果使用 stable sorting algorithm, 則 LSD sort 比較 單純•
sort 成”一桶一桶”以後不需要分開 sort•
用黑板舉例吧 ~~ ( 投影片做到發瘋了 )7
Radix Sort
• 方法 : 每次用某種方法把 items 分為 r 堆 . 然後再 concaten ate 起來 .
• 怎麼分為 r 堆 ?
• 舉例 : 每次使用某一位數的數字分堆 .
• 第一次依照個位數分為十堆 , 然後再放在一起 .
• 第二次依照十位數分為十堆 , 然後再放在一起 .
• …
• 直到完成 ( 共 d 個 pass).
• 最後放在一起的 items 即為 sort 好的 list.
• 用黑板舉例 .
•
8
有沒有一種天方夜壇
神秘的資料結構 Insert
Search
Delete
=O(1)
Hint: “ 以空間換取時間”
(key, data)
概念
很多很多有編號的櫃子問 : “ 菜瓜布”的資料去哪找 ? (“ 菜瓜布” , 資料 )
管理員 : “ 菜瓜布” 對 應到 1028 號櫃子
1028 管理員
如果箱子夠多 , 則花費在一個箱子裡面尋找的時間 =O(1)
概念
很多很多有編號的櫃子問 : “ 菜瓜布”的資料去哪找 ?
管理員 : “ 菜瓜布” 對 應到 1028 號櫃子
1028 管理員
Hash function:
h(k)
Hash table
櫃子數目 : b
每個位子可以放的資料數 :s
sb: 所有可以放數櫃子資料數目 key: 拿來當索引的東西
例如 : “ 菜瓜布”
T: 所有可能的 key 的數目 n: 所有要存入的 pair 的數目
Key density: n/T
loading density: n/sb
一些定義
•
h(k): hash function•
hash function 把 key 對應到一個數值 ( 通常為櫃子數 目 )•
有可能把不同的 key 對應到同一個數值•
( 但是沒關係 )•
如果 , 則 are synonyms with respect to .•
collision: 要把資料存進某櫃子的時候 , 該櫃子已經有 東西了•
overflow: 要把資料存進某櫃子的時候 , 該櫃子已經滿了•
if s==1, 則每次 collision 都會造成 overflow•
為什麼是 O(1)
•
當沒有 overflow 的時候 :•
計算 hash function 的時間 : O(1)•
進到某一個櫃子去 insert, delete, search 的時間都是 O (1)•
worst case 為尋找 s 個空間的時間 : 固定•
所以為 O(1)•
剩下的問題 :•
(1) 怎麼 implement 一個好的 hash function?•
(2) 當 overflow 發生的時候怎麼處理 ?Hash function
•
先要知道的事情 :•
不可能讓所有 key 都 map 到不同的櫃子•
( 因為通常 K 遠大於櫃子數目 )•
目標 :•
(1) 希望隨便取一個 key, 則平均來說它存到任何一個櫃 子的機率都是 1/b (b 為櫃子數目 ) ( 都是一樣的 )•
(2) 計算 hash function 的時間為 O(1)•
當 (1) 符合時 , 此 hash function 稱為 uniform hash fun ction一些 hash function 的例子
•
複習 : h(k) 把 k 轉成另外一個數字 ( 櫃子編號 )•
(1) Division: h(k)=k%D•
則結果為 0 ~ D-1 通常我們可以把 D 設為櫃子數目•
(2) Mid-square: h(k)=•
則結果為 0 ~ , 所以通常櫃子數目為•
一些 hash function 的例子
•
(3) shift folding•
用例子解釋 :•
k=12320324111220•
每隔幾位數切一份 . 例如 , 三位數 : ( 櫃子有 1000 個 )•
{123, 203, 241, 112, 20}•
h(k)=(123+203+241+112+20)%1000=699•
(4)folding at the boundaries•
{123,302,142,211,20}•
h(k)=(123+302+142+211+20)%1000=897一些 hash function 的例子
•
(5) digit analysis•
假設先知道所有的 key 了•
此時就可以尋找一個比較好的 hash function•
假設 k 有 5 位數 , 我們有 100 個櫃子•
則需要把 5 位數轉換成 2 位數•
則我們可以每次選某一位數來分類成 10 組•
最不平均的 3 個位數可以刪掉•
( 記得一開始說 , 最好可以使得分到某櫃子的機率都相 等 )Key 是 string 怎麼辦 ?
• 轉成數字 ! ( 然後再使用 hash function)
• 可不可以把不同字串轉成一樣數字 ?
• 答 : 可以 ! 反正 hash function 一樣已經會把不同 key 轉 成一樣的櫃子號碼了
• 方法 :
• (1) 把所有字串的 character( 數字 ) 加起來 , 進位的通通 丟掉 . ( 類似 checksum)
• (2) 把所有字串的 character ( 數字 ) 分別往左位移 i 格 , i 為該 character 在字串中的位置 , 然後通通加起來 .
• 舉例
Overflow 處理
•
兩種常用處理 overflow 的方法 :(1) Open addressing
Full!
Find another empty cabinet
(2) Chaining
Full!
多出來的吊在下面 注意 : 要確保能夠下次也能找到同一個地方 !
Open addressing – Linear probing
• 有好幾種方法 :
• (1) Linear probing
• ht[(h(k)+1)%b], ht[(h(k)+2)%b], …
• insert 的時候順著往下找 :
• 一直找到
• a. 有空位 填入
• b. 回到原來的位置 h(k) 了 , 則沒有空位可能要擴大 .
• search 的時候 , 一樣是從 ht[h(k)] 開始往下找 , 一直找到
• a. 有空位 k 不在 table 裡
• b. 找到了 , k 在 ht[(h(k)+j)%b] 的位置
• c. 回到原本的位置 h(k) 了 , k 不在 table 裡面
Open addressing – Linear probing
•
有沒有什麼壞處 ?•
尋找 overflow 出去的 element 需要花額外的時間 ( 不是 O (1) 了 )•
linear probing 讓在櫃子裏面的 key 容易集結在一起 ( 平 均尋找時間更長 )•
想想看為什麼Open addressing – 其他方法
•
其他方法 :•
(2)quadratic probing•
b 為一 prime number, 為 4j+3 之形式 ( 如 , 3, 7, 11, 1 9, …)•
(3)rehashing•
準備 m 個 hash function:•
依序尋找•
來做一些分析 ( 沒有推導 )
• Expected average number of key comparisons when looki ng up a key
• 尋找一個 key 時平均所需比較的 key 個數
• 因為其他的 operation 都只需要 O(1), 所以這個動作決定了 search 的 time complexity
• 失敗 ( 找到空位 ):
• 成功 :
• Worst case?
• 全部都連在一起 , 全部都填滿了
• O(n)
•
Chaining
•
之前的方法的缺點 ?•
尋找過程中 , 需多其他的資料的 hash 值 和現在要找的 key k 的 hash 值根本就不一 樣有點冤枉
•
所以採取”掛勾”的方法•
每個櫃子是一個 linked list•
搜尋的時候只會找掛在下面的 (h(k) 都 一樣 )Not here
結果在這邊 Not here
Not here
Chaining – Worst case
•
Worst case:•
全部都塞在同一個櫃子下面的 linked list•
time complexity 這樣是 ?•
O(n)•
小小的進步 : 底下可以用 binary search tree( 之後有 ba lanced 版 )•
可以進步到•
Chaining - Expected performance
•
每個櫃子的 chain 上面平均有幾個 pair?•
n: 總共存入的資料 pair 數目•
b: 櫃子數目•
所以假設使用 uniform hash function 的話•
平均一個 chain 有 n/b 個 pair ( 個 pair)•
這也是如果找不到的話 , 平均需要比較的次數•
如果找得到的話 , 平均需要找 chain 上面一半的 pair 數 目加上一次 ( 找到那個 pair 時所做的比較 )•
也就是說 ,•
Dynamic hashing
• 觀察 : 當 n/b 比較大以後 , O(1) 就開始崩壞 ( 往 O(n) 方向移 動 )
• 應變 : 所以要隨時觀察 n/b, 當它大過某一個 threshold 時就 把 hash table 變大
• 觀察 : 把 hash table 變大的時候 ,
• 需要把小 hash table 的東西通通倒出來 ,
• 算出每一個 pair 在大 hash table 的位置
• 然後重新放進大 hash table
• 有個可憐鬼做 insert 正好碰到應該 hash table rebuild 的時候 , 他就會等非常非常久 . T_T
Dynamic hashing
•
目標 : 重建的時候 , 不要一次把所以重建的事情都做完•
或許 , 留一些之後慢慢做 ?•
每個 operation 的時間都要合理•
又叫做 extendible hashing例子
k h(k)
A0 100 000
A1 100 001
B0 101 000
B1 101 001
C1 110 001
C2 110 010
C3 110 011
C5 110 101
h(k,i)=bits 0-i of h(k) Example:
h(A0,1)=0
h(A1,3)=001=1 h(B1,4)=1001=9
Dynamic hashing using directories
A0, B0 A1, B1 C2
C3 00
01 10
11 k h(k)
A0 100 000
A1 100 001
B0 101 000
B1 101 001
C1 110 001
C2 110 010
C3 110 011
C5 110 101
Insert C5 directory depth=
number of bits of the index of the hash table
h(C5, 2)=01=1
C5, overflow
A0, B0 A1, B1 C2
C3 000
001 010 011 100 101 110 111
C5
we increase d by 1
until not all h(k,d) of the keys in the cell are the same
動腦時間 :
如果原本的要加入 C1 呢 ?
如果第二步驟後加入 A4 呢 ? 答案 : p. 412-413
Dynamic hashing using directories
•
為什麼比較快 ?•
只需要處理 overflow 的櫃子•
如果把 directory 放在記憶體 , 而櫃子資料放在硬碟•
則•
search 只需要讀一次硬碟•
insert 最多需要讀一次硬碟 ( 讀資料 , 發現 overflow 了 ), 寫兩次硬碟 ( 寫兩個新的櫃子 )•
當要把 hash table 變兩倍大時 , 不需要碰硬碟 ( 只有改 d irectory)Directoryless Dynamic hashing
•
假設 hash table 很大 , 但是我們不想一開始就整個開來 用 (initialization 會花很大 )•
用兩個變數來控制的 hash table 大小 : r, q•
hash table 開啟的地方為 0, 之間•
r=2, q=2
0~q-1 及之間使用 h(k,r+1)
q~ 之間使用 h(k,r)
Directoryless Dynamic hashing
•
每次輸入的時候 , 如果現在這個櫃子滿了•
則開一個新的櫃子 :•
原本 q 櫃子裡面的東西用•
h(k,r+1) 分到 q 和兩櫃子裡•
注意有可能還是沒有解決問題•
多出來的暫時用 chain 掛在櫃子下面•
k h(k)
A0 100 000
A1 100 001
B4 101 100
B5 101 101
C1 110 001
C2 110 010
C3 110 011
C5 110 101
B4, A0 A1, B5 C2
C3 00
01 10 11
r=2, q=0
insert C5, full
A0
A1, B5 C2
C3 B4 000
01 10 11
r=2, q=1 C 5
100
問 : 再加入 C1 呢 ? ( 課本 p 415)