Presentasjon lastes. Vennligst vent

Presentasjon lastes. Vennligst vent

雜 湊 表.

Liknende presentasjoner


Presentasjon om: "雜 湊 表."— Utskrift av presentasjonen:

1 雜 湊 表

2 內 容 大 綱 雜湊表的定義 雜湊表的操作 雜湊函數 碰撞處理 雜湊表資料刪除 雜湊表的範例程式

3 雜湊表(hash table)是一種可以快速處理資料新增、搜尋及刪除的資料結構。
利用資料的鍵值(key)直接對應至儲存位置的方法,雜湊表可以在幾次的資料比對後就完成資料加入、搜尋及刪除的動作。

4 雜湊表的定義 (1/2) 雜湊表(hash table):
是一個將資料鍵值透過雜湊函數(hash function)轉換為資料儲存位置,而可快速進行資料加入、搜尋以及刪除的資料結構。 透過資料的鍵值(key)直接由雜湊函數(hash function)對應至儲存位置的方法,雜湊表可以在幾次的資料比對後就完成資料新增、搜尋及刪除的動作。 因此,雜湊表的各項操作的時間複雜度均為O(1)。下圖顯示雜湊表、雜湊函數與儲存位置的關係。

5 雜湊表的定義 (2/2) 位置 鍵值及資料 儲存位置 (position) 鍵值(key) 雜湊函數 (hash function)
位置 鍵值及資料 1 2 p-2 p-1 儲存位置 (position) 鍵值(key) 雜湊函數 (hash function) 雜湊表(hash table) 雜湊表、雜湊函數與儲存位置之關係。

6 雜湊表的操作 (1/1) 雜湊表的操作主要有以下三個: 新增(insert):將一新的鍵值加入雜湊表中。
刪除(delete):將一鍵值自雜湊表中移除。 搜尋(search):尋找某一鍵值所在位置。 下圖顯示一個執行各種雜湊表操作的實例。 假設k為鍵值、p為雜湊表大小,在下圖的實例中,採用k%p的公式(除法)來計算鍵值的儲存位置,而當二個鍵值k1、k2對應至相同儲存位置時,這稱為發生碰撞(collision),則採用線性探測(linear probing)的方式,依序尋找(k2+1)%p、(k2+2)%p、(k2+3)%p…等位置來作為新的儲存位置。

7 步 驟 操 作 輸 出 [0 雜湊表內容 p-1] 1. 新增(10) [ ] 2. 新增(26) [ ] 3. 新增(50) [ ] 4. 新增(66) [ ] 5. 新增(74) [ ] 6. 搜尋(66 ) 4 7. 刪除(66 ) [ ] 8. 搜尋(74 ) 6 9. -1 10. 新增(14) [ ] 11. 新增(23) [ ] 12. 新增(38) 雜湊表已滿例外

8 雜湊函數 (1/8) 雜湊表必須依賴雜湊函數(hash function)來計算出資料儲存位置,因此,雜湊函數與雜湊表有密不可分的關係。
H: H(key)=position 對雜湊表而言,若雜湊函數可以將所有的鍵值都對應到一個獨一無二的位置,則可以很單純的直接進行資料的加入、搜尋或刪除的動作。 然而,由於鍵值的可能值數目往往遠遠大於雜湊表的儲存空間,因此難免會有不同的鍵值對應到相同儲存位置的情況,我們將這種情況稱為碰撞(collision)。碰撞是雜湊表的運作中最需要用心解決的問題。

9 雜湊函數 (2/8) 雜湊函數可以進行資料鍵值與雜湊表儲存位置之間的轉換,一個好的雜湊函數必須具有以下的特點: 1. 計算簡單。
1. 計算簡單。 2. 碰撞(collision)少。 3. 不可造成雜湊表儲存位置局部偏重(bias)的狀況。

10 雜湊函數 (3/8) 以下我們介紹常用的雜湊函數: 1. 除法(division method):
H(key)=key mod p,其中p代表雜湊表的大小,它必須是質數(prime number)。我們將雜湊表大小p限制為質數是為了減少碰撞發生,例如,鍵值10,26,50,在p=8的情況下都會得到2的雜湊位置,即 H(10)=H(26)=H(50)=H(74)=2,若我們選擇p=7,則 H(10)=3,H(26)=5,H(50)=1,H(74)=4,其中完全沒有碰撞發生。

11 雜湊函數 (4/8) 2. 平方取中間為數法(mid-square method):
H(key)=mid(key2),其中mid可以取得key2的一些中間位數。因為一個鍵值平方的中間位數與鍵值的所有位數的數字大都沒有關係,因此,不同鍵值就有較大的機率對應到不同的位置;例如:若我們取萬位數、千位數及百位數,則 H(1234)=mid( )=227 H(4321)=mid( )=710

12 雜湊函數 (5/8) 3. 折疊法(folding method):
此方法將鍵值key分割為長度為L的幾個片段,使之除了最後一個片段之外,其他所有的片段長度均相同。分段完畢之後再將所有片段相加,即可得到最後的儲存位置,例如: key= ,取L=3,我們可將key分成下列幾個片段: 123、456、789、89,我們再將這些片段相加起來得到 =1457,其中1457就是我們儲存資料的位置。

13 雜湊函數 (6/8) 折疊法還有許多不同的做法,例如,我們可以將各片段進行不同的旋轉(如456可旋轉為564或645)或翻轉(如456可翻轉為654),相加的時候也可以選擇向左對齊或向右對齊相加(如89選擇向左對齊相加,則實際加入的值為890),甚至於再將最後片段相加的值再除以表格大小(質數p)。例如,若表格大小為97,則前述Key= 的實際儲存位置=1457 mod 97=2。

14 雜湊函數 (7/8) 4. 位數分析法(digit analysis method):
假如所有的鍵值已經事先知道了,則非常適合使用此方法。這個方法首先會針對每個位數中所有數字出現的頻率加以分析,並挑出其中分佈最均勻的幾個位數,用來作為計算位置的依據,例如,以鍵值為電話號碼為例(如下圖):

15 雜湊函數 (8/8) ˇ ˇ ˇ 我們注意到其中第4個,第6個及第7個電話號碼的分部最為平均,因此我們取這三個位置的數字作為最後儲存資料的位置,如此可以將碰撞發生的機會減到最低。 1 2 3 4 5 6 7 位置(取3位) 255 9 8 486 538 169 721 847 314

16 碰撞處理 (1/7) 即使經過仔細的設計,雜奏函數還是難免會有碰撞產生,此時,我們要使用碰撞處理(collision-handling)方法來處理這樣的狀況,以下我們說明常見的碰撞處理方法: 1. 線性探測(linear probing)法: 當碰撞發生時,就從發生碰撞的位置開始,一個一個的尋找未被佔用的儲存位置,直到找到一個未被佔用的位置或整個雜湊表完全被搜尋完畢為止。

17 碰撞處理 (2/7) 我們用C(key)=(H(key)+di) mod p來表示,其中di=1, 2, ..., p-1,表示第i次產生碰撞後,碰撞處理所探測的資料儲存位置。例如,鍵值10, 26, 50, 66, 74在探用除法為雜湊函數(p=7),並採用線性探測為碰撞處理法的情況下,所有鍵值對應的儲存位置為: C(10)=10%7=3 C(26)=26%7=5 C(50)=50%7=1 C(66)=(66%7=3)→4 C(74)=(74%7=4)→5→6

18 碰撞處理 (3/7) 2. 雙重雜湊(double hashing)法:
當碰撞發生時,就使用第二個預先設定的雜湊函數來進行新的第二個儲存位置的取得,如果在第二個位地也產生碰撞,則再利用第三個預先設定的雜湊函數來取得新的第三個儲存位置,依此類推,…。 例如,我們將雜湊函數設為: C1=H1(key)= key%p; C2=H2(key)= C1*key%p; C3=H3(key)= C2*key%p; 餘類推,…。

19 碰撞處理 (4/7) 在p為7的情況下,鍵值10, 26, 50, 66, 74的儲存位置為─ H(10)=10%7=3;
一般而言,採用雙重雜湊的碰撞處理法會比採用線性碰撞處理所需的探測次數來得少。

20 碰撞處理 (5/7) 3. 分別鏈結(separate chaining):
當碰撞發生時,就將資料儲存到鏈結串列中,這種方法的優點是不需要因為碰撞而需要重新計算資料的儲存位置,而其缺點是當碰撞次數(假設為t)較多時,使用鏈結串列來儲存這些鍵值發生碰撞的資料會較無效率,因為針對一個長度為t的鏈結串列而言,資料的刪除與搜尋的時間與t成正比。

21 碰撞處理 (6/7) 例如,當雜湊表大小p為7 的情況下,鍵值10, 26, 50, 66, 74, 17使用「分別鏈結」
方式儲存的情形如下: 雜湊表 1 2 3 4 5 6 7 50 10 74 26 66 17

22 碰撞處理 (7/7) 上述鍵值中的10, 66及17經過雜湊函數的計算,都對應到儲存位置3,因此,我們用鏈結串列將這三個鍵值分別儲存起來。

23 雜湊表資料刪除 (1/3) 對於使用線性探測或雙重雜湊探測碰撞處理法的雜湊表,在刪除資料時必須將資料位置標示為「已刪除」,以免讓後續的探測誤以為此位置為空而停止搜尋。 例如,在採用除法為雜湊函數(p=7)以及線性探測為碰撞處理法的情況下,鍵值10, 26, 50, 66, 74的儲存位置為如下圖(a),在刪除66之後形成下圖(b),此時若尋找鍵值74,則會形成如下圖(c)中回應「找不到」的錯誤狀況。此時應如下圖(d)一般,在刪除66之後將之標示為「已刪除」(我們將「已刪除」的鍵值以D表示),則可以如下圖(e)中所示的狀況,正確的找到欲搜尋的資料。

24 雜湊表資料刪除 (2/3) 50 10 66 26 74 50 10 26 74 50 10 26 74 1 2 3 4 5 6 1 2 3 4 5 6 1 2 3 4 5 6 刪除 66 尋找 74 66 74,回應找不到 74 74 74 (a) (b) (c)

25 雜湊表資料刪除 (3/3) 50 10 D 26 74 50 10 D 26 74 74,線性探測往下找 線性探測往下找 回應找到 (d)
1 2 3 4 5 6 1 2 3 4 5 6 74,線性探測往下找 線性探測往下找 回應找到 (d) (e)

26 雜湊表的範例程式 (1/11) 以下我們以Java語言撰寫雜湊表的範例程式,我們採用除法為雜湊函數,並採用線性探測為碰撞處理方法。我們並假設所有的鍵值均為正數,而使用-1代表已刪除之鍵值,使用0代表未被佔用的儲存位置。 1:     //檔名:雜湊表類別.java 2:     //說明:「雜湊表類別」範例程式 3:     // 假設所有的鍵值均大於0,鍵值為-1則代表鍵值已刪除 4:     public class 雜湊表類別 { 5:     private int[] 儲存陣列; //儲存鍵值之陣列 6:     private int p; //p代表儲存陣列大小 7:     雜湊表類別(int 大小參數) { 8:     儲存陣列=new int[大小參數]; 9:     p=大小參數; 10:   }

27 雜湊表的範例程式 (2/11) 11: public int 搜尋(int k) { //k代表鍵值 12: int 位置;
13:     位置=k%p; 14:     if (儲存陣列[位置]==k) return 位置; 15:     else return 搜尋碰撞處理(位置, k); 16:     } 17:     public int 搜尋碰撞處理(int 碰撞位置, int k) { 18:     int 位置=碰撞位置; 19:     while(true) { 20: 位置=(位置+1)%p; 21: if(位置==碰撞位置) return -1; //「位置」指標已繞一圈, 表示整個空間已滿 22: if(儲存陣列[位置]==k) return 位置; //傳回k位於雜湊表中之位 23: if(儲存陣列[位置]==0) return -1; //傳回-1代表找不到 24: }

28 雜湊表的範例程式 (3/11) 25: } 26: public int 新增搜尋(int k) { //k代表鍵值 27: int 位置;
25:    } 26:    public int 新增搜尋(int k) { //k代表鍵值 27:    int 位置; 28:    位置=k%p; 29:    if (儲存陣列[位置]==0) return 位置; 30:    else return 新增搜尋碰撞處理(位置, k); 31:    } 32:    public int 新增搜尋碰撞處理(int 碰撞位置, int k) { 33:    int 位置=碰撞位置; 34: while(true) { 35: 位置=(位置+1)%p; 36: if(儲存陣列[位置]==0) return 位置;//找到空的位置 37: if(位置==碰撞位置) return -1; //「位置」指標已繞一圈,表 示整個空間已滿 38: //傳回-1代表找不到未被佔用之位置

29 雜湊表的範例程式 (4/11) 39:    } 40:    } 41:    public void 新增(int k) throws 雜湊表滿出例外 { //k代表鍵值 42:    int 位置=新增搜尋(k); 43:    if (位置>=0) 儲存陣列[位置]=k; 44:    else throw new 雜湊表滿出例外(); 45:    } 46:    public void 刪除(int k) throws 資料不存在例外 { //k代表鍵值 47:    int 位置=搜尋(k); 48: if (位置>=0) 儲存陣列[位置]=-1; //使用-1代表鍵值已刪除 49:   else throw new 資料不存在例外(); 50:   }

30 雜湊表的範例程式 (5/11) 51: public String toString( ) { 52: String 傳回字串="";
53:     for (int i=0;i<p;++i) 54:     傳回字串+=(儲存陣列[i]+“ ”); //將每一項資料以一個空白隔 開併入傳回字串中 55:     return 傳回字串; 56:     } 57:     } //類別:雜湊表類別 定義區塊結束 58:     class 雜湊表滿出例外 extends Exception { } 59:     //建立一個例外類別,以便在雜湊表滿出時可以被丟出 60: class 資料不存在例外 extends Exception { } 61: //建立一個例外類別,以便在欲刪除資料不存在時可以被丟出

31 雜湊表的範例程式 (6/11) 1: //檔名:雜湊表測試.java 2: //說明:「雜湊表類別」之測試程式
2:     //說明:「雜湊表類別」之測試程式 3:     import javax.swing.*; 4:     public class 雜湊表測試 extends JApplet { 5:     public void init( ) { 6:     雜湊表類別 雜湊表=new 雜湊表類別(7); 7:     String 顯示字串=""; 8:     try { 9:     顯示字串+="操作\t輸出\t0(雜湊表內容)p-1"; 10:  顯示字串+="\n新增(10)";

32 雜湊表的範例程式 (7/11) 11: 雜湊表.新增(10); 12: 顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後
11:     雜湊表.新增(10); 12:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 併入顯示文字中 13:     顯示字串+="\n新增(26)"; 14:     雜湊表.新增(26); 15:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 16:     顯示字串+="\n新增(50)"; 17:     雜湊表.新增(50); 18:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 19:    顯示字串+="\n新增(66)"; 20: 雜湊表.新增(66); 21: 顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後併 入顯示文字中 22: 顯示字串+="\n新增(74)";

33 雜湊表的範例程式 (8/11) 23: 雜湊表.新增(74); 24: 顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後
23:     雜湊表.新增(74); 24:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 併入顯示文字中 25:     顯示字串+="\n搜尋(66)"; 26:     顯示字串+="\t"+雜湊表.搜尋(66); 27:     顯示字串+=“\t”+雜湊表; //將整個雜湊表之內容轉為字串後 28:     顯示字串+="\n刪除(66)"; 29:     雜湊表.刪除(66) ; 30:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 31:     顯示字串+="\n搜尋(74)"; 32:  顯示字串+="\t"+雜湊表.搜尋(74); 33:  顯示字串+=“\t”+雜湊表; //將整個雜湊表之內容轉為字串後併入顯示文字中

34 雜湊表的範例程式 (9/11) 34: 顯示字串+="\n搜尋(66)"; 35: 顯示字串+="\t"+雜湊表.搜尋(66);
38:     雜湊表.新增(14); 39:     顯示字串+="\t\t"+雜湊表; //將整個雜湊表之內容轉為字串後併入顯示文字中 40:     顯示字串+="\n新增(23)"; 41:     雜湊表.新增(23); 42:     顯示字串+="\t\t"+雜湊表; //將整個雜湊表之內容轉為字串後併入顯示文字中 43: 顯示字串+="\n新增(38)";

35 雜湊表的範例程式 (10/11) 44: 雜湊表.新增(38);
44:     雜湊表.新增(38); 45:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 併入顯示文字中 46:     顯示字串+="\n新增(5)"; 47:     雜湊表.新增(5); 48:     顯示字串+=“\t\t”+雜湊表; //將整個雜湊表之內容轉為字串後 49:     } 50:     catch(雜湊表滿出例外 e) {顯示字串+="\t雜湊表滿出"; } 51:     catch(資料不存在例外 e) {顯示字串+="\t欲刪除之資料不存在"; } 52:     finally {JOptionPane.showMessageDialog(null,new JTextArea(顯示字串));} 53:  } //方法:init() 定義區塊結束 54:  } //類別:雜湊表測試 定義區塊結束

36 雜湊表的範例程式 (11/11) 1: <html> 2: <h1>「雜湊表測試」執行中<h1>
3: <applet code="雜湊表測試.class" width=350 height=100> 4:   </applet> 5:   </html> 程式執行結果

37 Q&A

38 程式執行結果


Laste ned ppt "雜 湊 表."

Liknende presentasjoner


Annonser fra Google