Chapter 14 搜尋法 - Ian-Liu-1990/Data-Structure GitHub Wiki
快速複習
***優 點 | 缺 點 | |
---|---|---|
循序 | 1. 資料不用事先排序2. 適合動態資料3. 少量搜尋 | O(N),不適合N大 |
二分搜尋 | 適合大量資料O(logN) | 1. 需要事先用陣列排好,且需要索引值,適合靜態2. 不適合動態資料 |
內插搜尋 | 適合大量且分佈平均資料,O(loglogN) | 1. 需要事先用陣列排好,適合靜態,資料不平均退化成循序O(N)2. 不適合動態資料 |
雜湊法 | ||
費事搜尋 | 適合大量資料O(logN),只依靠"加減"法 | 1. 需要事先用陣列排好,資料少效率差 |
1. 循序搜尋法
先決條件?
一. 循序搜尋法的適用性- 各種儲存體包含直接存取或循序存取皆可以用循序搜尋
- 資料不用事先排序
- 鏈結串列只能使用循序
- 若事先知道資料取用頻率,則可進行安排提高效率 <= 是否知道取用頻率(由高至低排列取用)會影響效能?
- 適合動態資料
- N很大時非常不合適
二. 循序搜尋法的搜尋時間分析
- Best : O(1)
- Worst : O(N)
- Avg : O(N) <= 平均比較次數 : (1 + 2 + ... N)/N = ((1+N)*N)/2N = (1+N)/2
2. 二分搜尋法
先決條件?
一. 二分搜尋法的適用性- 資料一定要先排序(排序演算法時間)過 : 快速排序O(NlogN)
- 適合靜態資料
- 資料必須儲存在直接存取裝置Core memory,Disk
- 儲存裝置必須具有隨機存取能力,如陣列,需要依索引位置跳到該位置上
- 適合資料量大,資料量小會因為二分搜尋法OverHead大,反而比循序時間差
與二元搜尋樹無關
二. 二分搜尋法的搜尋時間分析三. 2種實現方法
3. 費式搜尋法(冷門,缺?)
一. 費式搜尋法的適用性[先決條件?]
- 資料一定要先排序過,需要額外陣列
- 適合靜態資料
- 不需要使用除法,只用加減法即可OverHead比二分搜尋小
- 適合資料量大,資料量小會OverHead大,反而比循序時間差
二. 費式搜尋法的搜尋時間分析(與二元搜尋樹無關)
- Avg : O(LogN)
4. 內插搜尋法
一. 內插搜尋法的適用性[先決條件?]
- 資料一定要先排序過,需要額外陣列
- 適合靜態資料
- 適合平均分布或分布均勻的資料進行搜尋
- 適合資料量大,資料量小會OverHead大,反而比循序時間差
I = I(low) + {(I(upper) - I(low))(K - K(low)) / (K(upper) - K(low))}
二. 內插搜尋法的搜尋時間分析(與二元搜尋樹無關)
5. 雜湊法(Hashing)
I. 雜湊法原理
- 定義 : 使用雜湊函式(Hashing Function)F(X),做為Key X與Address之間的對應,在搜尋資料時先使用function將Key帶入,以計算出位置在存取資料
II. 雜湊術語
-
桶子(Buckets) : 將雜湊表等分為M個桶子,每個桶子都有一個唯一的位址(或索引),每個桶子都可以儲存若干筆資料
-
槽(Slots) : 將每個桶子再分為數個槽(Slots),每個槽可以存放一筆資料
-
碰撞(Collision) : 不同的鍵值可能雜湊到相同的位址,有Collision並不一定有Overflow
-
滿溢(Overflow) : 當Collision產生,且Bucket中無多餘的Slot可存資料稱之,有Overflow,則必有Collision發生
-
識別字密度(計算題) : 若全部識別字或Key值共有T可能值,而當下存在雜湊表中有N筆資料,則比率N/T為識別字密度
-
負載密度(計算題) : 表示目前雜湊表的空間使用率,a = N/(m*s),N目前表格中的總資料項數,m為桶子總數,s為每個桶子的槽數
-
完美雜湊函數 : 若任兩項資料的鍵值,以雜湊函數計算出來的位址皆不相同
III. 雜湊函數[不用管計算而是要知道特性]
-
中間平方法 ( Mid - square ) : 將Key平方後,取出中間某些位元來當作資料儲存位址。
-
折疊法 ( Folding ) : 將Key分為數段,除了最後一段外,其餘各段皆須等長,然後將每一段相加,即可得到其所對應的位址。
- 相加的時候,有兩種方式:
-
位移折疊 ( Shift Folding ) : 將各段資料直接相加。
-
邊界折疊 ( Folding at the boundaries ) : 將奇數位段或偶數位段反轉後相加。
-
- 相加的時候,有兩種方式:
-
除法 ( Division ) : 利用Mod運算,將Key除以雜湊表的大小M(桶子的數目),取其餘數當做索引。這個位址介於 0 ~ M-1 之間。
- 使用除法時,一般建議利用質數會有較佳的效果。即 H( X ) = X mod M
-
數字分析法 ( Digit Analysis ) : 已經事先知道會出現的Key值
-
觀察數字分析法:利用觀察法,將Key分佈不平均的數字刪除,其餘保留為Hash位址。
-
統計數字分析法:利用統計方法分析鍵值各位數的分析情形,求出Hash位址。
-
-
直接定址法:取關鍵字或關鍵字的某個線性函數值為雜湊地址。
IV. 碰撞解決或滿溢處理(Overflow Handling, Collision Resolution)
A. 開放定址法 : 搜尋主要區域中開放(未被佔據)的位址並放置新記錄
-
Linear Probing : 繼續檢查下一個Bucket直到為空Bucket,若已檢查到最後一個Bucket則循環從Table最開頭檢查;已搜尋完一圈為止,表示雜湊表滿
-
平方探索(Quadratic Probing) : 當碰撞而且溢位時,在雜湊表開放空間中尋找可用位置,方法是第一次碰撞位置(F(x)"+或-"(i^2))mod m,在避免相近Key聚集,i為每次發生碰撞的次數,從i = 0(無碰撞),i = 1(碰撞1次)...i = N(碰撞N次)次數累加
-
平方餘數(Quadratic Residue) : 當碰撞而且溢位時,在雜湊表開放空間中尋找可用位置,方法是第一次碰撞位置,交錯計算(F(x)+/-(i^2))mod m,在避免相近Key聚集,i為每次發生碰撞的次數,從i = 0(無碰撞),i = 1(碰撞1次)...i = N(碰撞N次)次數累加
-
重複探索(Rehashing) : 前者任意排列,後者設置好一套雜湊函數,當溢位發生依序使用函數,採用另一個雜湊函式產生一個固定的增量。每隔T個位置檢查一次
-
double hashing : 依照題目指示將值塞入雜湊表,發生碰撞再依照i為每次發生碰撞的次數,從i = 0(無碰撞),i = 1(碰撞1次)...i = N(碰撞N次)次數累加,添加第二函數計算
獨立串列(Separate Chaining) : 碰撞發生,以Link list方式串連在同一Bucket中,使每一個Bucket各自有一個鏈結新記錄
B.雜湊碰撞特性-<相近的Key因為群聚產生的問題>?
V.聚集(Cluster)
- 在函數地址的表中,雜湊函數的結果不均勻地占據表的單元,形成區塊,雜湊到區塊中的任何關鍵字需要查找多次試選單元才能插入表中,解決碰撞,卻造成時間浪費。對於開放定址法,聚集會造成性能的災難性損失,是必須避免的。
-
線性探測產生一次聚集(primary clustering) : 任意一個落入此區間的元素都要一直探測到區間末尾,最終將加入到此區間內。導致落在區間內的關鍵字Key要多次探測才能找到合適的位置,並且還會繼續增大這個連續區間,使探測時間變得更長
-
平方探測的二次聚集(secondary clustering) : 解決了線性探測法的一次聚集,但是關鍵字key散列到同一位置後探測時的路徑是一樣的而且依樣拉長探測時間
-
Open Addressing時,需注意直接或簡單的Deletion的資料位置調整:Linear Probing若簡單或直接刪除一個資料,會因為一次聚集使其他資料找不到
-
問題 : F(x) = x mod m, 碰撞使用Linear Probing,插入39, 47, 21, 11, 7, 67, Delete 39會使67找不到
-
解決 : "重組調整,記號法"
-