1 / 31

第 10 章 赫序函數

資料結構設計與 C++ 程式應用 Fundamentals of Data Structures and Their Applications Using C++. 第 10 章 赫序函數. 資料結構設計與 C++ 程式應用 版權所有 禁止重製. 何謂赫序函數 (Hashing Function ). 赫序函數 (Hashing Function):

cora-flores
Télécharger la présentation

第 10 章 赫序函數

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 資料結構設計與C++程式應用 Fundamentals of Data Structures and Their Applications Using C++ 第10章 赫序函數 資料結構設計與C++程式應用 版權所有 禁止重製

  2. 何謂赫序函數(Hashing Function ) • 赫序函數(Hashing Function): 透過一個數學函數來計算(或轉換)一個鍵值所對應的位址 • 碰撞(Collision): 當一個位址同時被兩個或兩個以上的鍵值所對應時,我們稱此現象為碰撞(Collision)

  3. 傳統的赫序搜尋法 • 除法(Division Method) h(k)=(k mod m)+1 k:代表資料的鍵值。 m:代表位址空間的大小。 根據經驗,m為偶數時較易發生碰撞。因此,專家們建議要嘛乾脆取一個質數當做m;不然的話,m可以找一個奇數且沒有任何一個質因數小於20者為之。 【例】 除法 鍵值集合 k ={34,59,72,95}。令m=7,則利用 h(k)=(k mod 7)+1,可以將鍵值34,59,72,95分別存放到第7,第4,第3及第5號位址上。

  4. 傳統的赫序搜尋法 • 平方取中法(Midsquare Method) 鍵值:k 鍵值平方:k2 令 m=99…9代表位址空間的大小,且 m 為 t 位數。則取 k2的中間t位數之值當作鍵值 k 所對應的位址。 【例】 平方取中法 設鍵值 k=113586。令m=9999,故 m 為4位數正整數。則 h(k)=k2取中間4位數 =12901779396取中間4位數 =1779。

  5. 傳統的赫序搜尋法 • 疊合法(Folding Method) 將鍵值 k 切割成若干長度相等的區塊,將之相加,再 mod m(意即除以m取餘數)而得,其中 m 為位址空間的大小。 【例】 疊合法 設鍵值 k=187249653,且 m=1000。第一區塊 第二區塊 第三區塊 則首先將 k 切成三個區塊:187,249,653 187 + 249 + 653 = 1089。 h(k) = 1089 mod 1000 = 89。原第一區塊的翻轉原第三區塊的翻轉 也有人建議為了更減少碰撞之機率,有時亦可考慮將所切割的各區塊,在相加之前先將奇數號的區塊翻轉過來,再做加法。如上例: 781 249 +356 1386 h(k) = 1386 mod 1000 = 386。

  6. 傳統的赫序搜尋法 • 基數法(Radix Method) 將鍵值視為某一基數數系中的數值,再將該數值轉換回原鍵值所在的基數數系,接著,取出該數的某些位數值當做赫序函數的對應值。 鍵值:(k)p,其中 p 為一個基數。 ↓看成 (k)q,其中 q>p,且 q 與 p 互質。 ↓從 k 中取出一部份 k' (k')p當做 h(k)之值 【例】 基數法 鍵值 k=(530476)10,在此數中,P=10。首先將k=(530476)10看成(530476)11,此時 q=11,且q與p互質。再將(530476)11轉換回原 k 所在的基數數系;亦即,(530476)11=5*115 + 3*114 + 4*112 + 7*111+6*110 = (849745)10。接著取後三位數當作赫序函數值;亦即 h(k) = 745。

  7. 傳統的赫序搜尋法 • 代數碼法(The Algebraic Coding Method) 【例】 代數碼法 k = (1615)10 = (011001001011)2 =(a1,a2,...,a12)2。因此,r=12。 造一個多項式:K(x)=x+x2+x5+x8+x10+x11。 令位址空間大小:m=210=1024,故t=10。 造一個多項式:p(x)=x10+x8+x5+x4+x2+x+1。 計算 K(x) mod p(x)=x9+x7+x5+x4+x3。 故 h(1615)=(1010111000)2 = 696。

  8. 傳統的赫序搜尋法 • 乘法(Multiplication Hashing) 鍵值:k 常數:c 且 0<c<1 位址空間大小:m h(k):+1。 請注意:ck mod 1代表 ck 這個數的小數部份之值。 • 位數分析法(Digit Analysis) 位數分析法主要用於十進位制的各個鍵值之位數比較,採用分佈較均勻的若干個位數值做為每一個鍵值的赫序函數值。

  9. 解決碰撞的方法 • 循序定址法(Linear Probing/ Linear Open Addressing) 原理上,當 h(ki)=α=h(kj)時,表示 kj 與 ki撞在一起了。這時候,我們可以沿著位址 α 的下面,逐號地尋找一個空的位置來讓 kj棲身。如果一路找到位址空間的最後一號位置都沒有找到空位置的話,則可以再折回位址空間的第一號位置,再從上往下去搜尋,直到找到 α 的前一號位置為止。

  10. 解決碰撞的方法 • 多次定址法(Quadratic Probing) 當有碰撞產生時,利用較不規則的跳躍去尋找下一個可能空的位置。 當鍵值 k 的赫序函數值 h(k) 和其它的鍵值撞在一起時,可以第一次考慮試 (h(k)+12) mod m之位址看看該位置是否有空;否則的話,第二次可以試 (h(k)+22) mod m之位址看看,依此類推。

  11. 解決碰撞的方法 • 亂數法(Random Method) 當產生碰撞時,則將該鍵值以亂數赫序函數再重新計算一個新址。如果用數學描述法來表示,亂數法可以寫成: h(k)+s(i),1≦ i ≦m-1。 s(i)為一個虛擬亂數產生程式,i為該亂數產生程式的種子(Seed)。例如 i← (i+c) mod m,假設 i 為亂數產生程式的種子(亦即起始值),而 c 與 m 互質。令 c=7,m=11,且一開始的時候,i=3,則產生的亂數為 10,6,2,9,5,1,8,4,0,7,3。

  12. 解決碰撞的方法 • 重複赫序法(Rehashing) 當有碰撞現象產生時,再改用事先準備好的其它種赫序函數計算出不同的位址,若再碰撞,則再找出另一個赫序函數來計算位址,依此類推。因此,重複赫序法需要事先準備一些赫序函數 h1,h2,…,hr,以備不時之需。 • 開放定址法(Open Addressing),又稱掛籃法(Bucketing) 讓每一個位置的空間加大,就像一個籃子一般,讓它可以存放不只一個鍵值,使之不致於因為稍一碰撞,就非得四處尋找蔽護不可。然而,縱使一個籃子可以多放幾個鍵值,畢竟它也有滿溢的時候,當籃子滿溢時究竟該怎麼辦呢?做法很簡單,可以再造一個籃子,讓新的籃子和舊的籃子邏輯上相連在一起。

  13. 解決碰撞的方法 • 串列法(List Method) 利用一塊自由區 (Free Storage Area) 做為碰撞之鍵值棲身之難民營,當有碰撞產生時,就將這個後來的鍵值放到自由區的空位置裡,而利用指標與原住民 (即較早赫序到同一位址之鍵值) 相連。

  14. 赫序函數之建議與評估 一個較合用的赫序函數需考慮下列幾個因素 • 靜態資料或動態資料 • 定址所需時間 • 用硬體來發展赫序函數 • 鍵值長度 • 鍵值基數 • 位址空間的大小 • 資料存取的頻率 • 對於不成功的存取(Unsuccessful Search),能否很快地確定所要尋找的鍵值根本不在檔案裡?

  15. 赫序函數之建議與評估 赫序函數好壞的評估原則: • 存取資料的速度快嗎? • 資料的新增是否方便? • 刪除資料是否方便? • 記憶體是否佔用很多? • 有沒有充份利用到鍵值的大小? • 有沒有利用到鍵值的存取頻率?

  16. 動態完美赫序函數 動態赫序函數大致上可以分成二類: • 需要索引輔助區域的動態赫序函數 : Litwin的虛擬赫序(Virtual Hashing)、 Larson 動態赫序(Dynamic Hashing)、 Fagin等人的延展赫序(Extendible Hashing) 。 2. 不須要索引輔助的動態赫序函數: Litwin的Trie Hashing 。

  17. 動態完美赫序函數 • Larson的動態赫序函數 利用了串列樹(Link-Tree)的架構,建構了一個稱之為索引的輔助區域,藉以偵測當檔案有新記錄加入時,其所指定儲存的區段當時是否已經放滿了記錄?若是,則需將該區段一分為二。至於這些須要儲存的記錄,應被放置於那一個區段?是由我們所謂的動態赫序函數對應於該記錄的主鍵值所決定的。

  18. 動態完美赫序函數 • Larson的動態赫序函數 【例】 H0為一赫序函數,用來決定想要儲於檔案中的記錄類別,進而利用該類別決定儲存記錄的區段。

  19. 動態完美赫序函數 • Larson的動態赫序函數 假設有一筆新的記錄其主鍵值為 “in”,欲加入檔案中,而且H0(“in”)=1,但因每個區段最多只能容納四筆記錄,故區段0便發生了碰撞的現象,因此必須對區段0做一次分裂(Split)的程序處理。 因此可到以下結果:

  20. 動態完美赫序函數 • Larson的動態赫序函數 索引呈現一個樹林(Forest)的結構,而每棵樹都是二元樹(Binary Tree)。在這些樹的節點中屬於外部節點者(亦即所謂的樹葉(Leaf)都會指到一個區段的位址上;因此,當使用者想找尋某一筆記錄時,首先利用 H0函數來分辨其在索引中所屬的二元樹。決定完所屬的二元樹之後,再檢查其是否為外部節點(External Node)?

  21. 動態完美赫序函數 • Litwin的虛擬赫序函數 假設每一個區段最多可以存放四筆記錄。 以 N=100 為例,將記錄分散在編號0至99的區段中,而如圖(a),當新加入一筆主鍵值為4900的記錄時,造成區段0發生了碰撞的現象,因而對應於區段0之赫序函數的j值必須加1,故造成了區段0中的五筆記錄自然地分散到區段0和區段100,如圖(b)。

  22. 動態完美赫序函數 • 延展赫序函數 保證在尋找(Search)記錄的過程中絕對不曾超過兩次的磁碟機讀取次數(Disk Access Time)。 【例】

  23. 動態完美赫序函數 • 延展赫序函數 若有一筆新的記錄其主鍵值為“in”且 H(“in”)=01…,則因區段0現已經額滿了,所以該區段會一分為二,將原來區段0中的記錄分散在區段0和區段3。分裂後的結果 如下:

  24. 動態完美赫序函數 • 延展赫序函數 假如因某一筆新記錄的加入而造成對於某一個區段的碰撞,則必須做分裂的動作,而且由於這一個分裂的動作使得索引中的d值加1,則整個索引的節點數將會爆增一倍。

  25. 動態完美赫序函數 • Trie赫序函數 儲存記錄時須依據主鍵值的大小次序來儲存 。 Trie的資料結構 :

  26. 動態完美赫序函數 • Trie赫序函數 【例】 檔案開始時空無一物,如圖(a)所示。假設目前有四筆記錄儲存進來,則區段的內容如圖(b)所示。

  27. 動態完美赫序函數 • Trie赫序函數 此時若有一筆新的記錄且其主鍵值為 "a" 欲加入此檔案,便發生了碰撞的現象,我們必須將區段 0 做分裂處理。

  28. 動態完美赫序函數 • Trie赫序函數 將其隱含的意義以更明確的類似二元樹的架構表示出來

  29. 動態完美赫序函數 • Trie赫序函數 當加入的新記錄到達一定的程度之後,區段 0 或區段 1 可能再度發生碰撞

  30. 動態完美赫序函數 • Trie赫序函數 圖(a) 中,Trie 0 節點的 LP=-1,此乃因為原來 Trie 0 的 LP 的區段發生了碰撞分裂,而該處理程序會建造出一個新的區段和 Trie 節點。圖(b)將此五筆記錄重新依 DN=0,DV='i' 的規則分配到區段 0 和區段 2。

  31. 動態完美赫序函數 • Trie赫序函數 Trie 的另一種表示法

More Related