【復習筆記】數據結構-檢索
阿新 • • 發佈:2018-12-08
磁盤訪問 span 不同 數字分析 clas temp 分析法 區間 再次
性能用ASL(查找成功時的平均查找長度)來衡量
線性表檢索
順序檢索
- 逐個比較
- 優點:插入元素可以直接加在表尾
- 缺點:檢索時間太長
二分檢索法
- 條件:序列必須有序
- 實現:
1 template <class Type> int BinSearch (vector<Item<Type>*>& dataList, int length, Type k){ 2 int low=1, high=length, mid; 3 while (low<=high) { //結束條件!! 4 mid = (low+high)/2
- 性能分析:最大檢索長度(完全二叉樹的高度):$log_2^{n+1}$;失敗的檢索長度$log_2^{n+1}$向上或向下取整;平均的檢索長度和最大檢索長度接近:$log_2^{n+1}-1$
- 優點:快
- 缺點:要排序,不易更新
分塊檢索
- 思想:兩級檢索。將元素分為多塊,塊內的關鍵碼不一定有序,但塊間有序(前塊中最大關鍵碼<後塊中最小關鍵碼);索引表中包含每個塊最大的關鍵碼和起始位置,以及每個塊裏元素的個數。
- 性能:查找長度是兩級檢索的查找長度總和
- 優點:更新容易
- 缺點:
- 需要一個輔助索引表
- 分塊需要排序
- 元素分布不均勻、大量插入或刪除時性能下降
散列表檢索(HASH)
基本概念
- 帶檢索的關鍵碼K
- 散列函數h(K):關鍵碼K的存儲位置
- 負載(裝填)因子:$α=\frac{n}{M}$(n,散列表中已有結點數;M,散列表空間大小)
- 沖突:將不同關鍵碼映射到相同散列地址
- 同義詞:發生沖突的兩個關鍵碼
各類方法
除余法
- $h(x)=x mod M$
- M值通常選擇質數,有利於均勻分布
- 潛在缺點:連續的關鍵碼映射為連續的散列值,散列性能降低
乘余取整法
- $h(x)=n*(A*key\% 1)$
平方取中法
- 求關鍵碼的平方,再取其中的幾位或其組合作為散列地址
- 最接近隨機化
數字分析法
- 分析每一位上不同符號出現頻率,選取其中各種符號均勻分布的若幹位作為散列地址
基數轉換法
- 把關鍵碼看成是另一進制上的數後,再把它轉換成原來進制上的數。取其中若幹位作為散列地址
- 一般取大於原來基數的數作為轉換的基數,並且兩個基數要互素。
折疊法
- 將關鍵碼分割為位數相同的幾部分,取這幾部分的疊加和(舍去進位)作為散列地址。
- 兩種疊加方法:移位疊加(各部分以最後一位對齊);分界疊加(沿各部分的分界來回折疊,對齊相加)
沖突的解決方法
開散列方法
拉鏈法(適用於內存)
- 思路:所有同義詞鏈接在同一鏈表,以拉鏈狀拉開。每個槽定義為一個鏈表的表頭。
- 這時候α可以大於1,但一般還是取小於1
- 優點:適合表長不確定的情況,增刪結點容易。
- 缺點:如果散列表元素在磁盤裏,拉鏈法不適用。
- 同義詞表中的元素元素在不同的磁盤頁中的話,檢索一個特定關鍵碼時將引起多次磁盤訪問,增加檢索時間
桶式散列(適合存儲於磁盤的散列表)
- 思想:散列文件記錄分為若幹桶,每個桶包含幾個頁塊,每個頁塊有若幹記錄,各頁塊用指針鏈接。h(k)表示具有關鍵碼K的記錄所在桶號。
- 性能:桶目錄表最多一次訪外,逐個檢查桶內頁塊,平均訪外次數為桶內頁塊數一半。修改、插入等需另1次訪外寫外存。
閉散列方法(開地址法)
基本聚集:堆積,散列地址不同的記錄,爭奪同一後繼散列地址,導致很長的探查序列,偽隨機探查和二次探查可以消除基本聚集
二級聚集:如果兩個關鍵碼散列到同一基地址還是得到同一探查序列。
- 把發生沖突的關鍵碼存儲在散列表中另一個空地址內
- $d_0=h(K)$為K的基地址
- $d_i=d_0+p(K,i)$是後繼散列地址,p(K,i)是探查函數
- 搜索空位時,若基地址結點已被占用,逐個尋找探查序列中的空閑位置。如果找遍了都沒有,說明列表滿了,報告溢出。
線性探查法
- 思想:逐個逐個往後找……$p(K,i)=i$
- 優點:所有的存儲位置都可以作為插入記錄的候選
- 缺點:聚集
- 改進:每次跳過c個槽而不是1個
- 第i個槽是$(h(K)+ic)mod M$,探查函數是$p(K,i)=i*c$
- 基位置相鄰點記錄不會進入同一個探查序列
- 但相隔c的還是糾纏在一起
二次探查
- 地址公式:$d_{2i-1}=(d+i^2)%M;d_{2i}=(d-i^2)%M$
- 探查函數:$p(K,2i-1)=i*i;p(K,2i)=-i*i$
- 基本聚集消失
偽隨機數序列探查
- 探查函數$p(K,i)=perm[i-1]$
- perm是一個長度為M-1的數組,一個值在[1,M-1]的隨機序列
- 基本聚集消失
雙散列探查法
- 思想:使用兩個散列函數$h_1$和$h_2$
- 若在$h_1(K)=d$發生沖突,計算h_2(K)得到的探查序列為探查序列:$d_i=(d+i*h_2(key))%M$
- $(d+h_2(K))\% M$
- $(d+2h_2(K))\% M$
- $(d+3h_2(K))\% M$…
- 探查函數:$p(K,i)=i*h_2(K)$
- $h_2(K)$必須與M互素(否則可能會發生同義詞地址的循環計算)
- 優點:不易產生聚集
- 缺點:計算量增大(也不是很大)
閉散列的算法設計
- 插入
- 找到基地址空間
- 基地址空間不空,循環找下一個探查序列直到關鍵碼值相同或找到空位
- 檢索
- 基地址空間未被占用,檢索失敗,否則將在基地址中的值和K比較,相等則成功。
- 否則查找探查序列循環。直到找到相等關鍵碼或未被占用的地址空間。
- 刪除
- 開散列可以隨意刪除
- 閉散列只能作標記,不能真正刪除,除非之後再次分配空間。不然會影響檢索操作
- 設置一特殊的標記位(墓碑):單元被占用\空單元\已刪除
- 插入時遇到墓碑,要繼續沿著探查序列找到真正空位,為了防止插入兩個相同的關鍵碼
- 效率分析:不依賴於n,與α有關。α小時性能高。$α\leq 0.5$時,大部分操作的分析預期代價都小於2。負載因子的臨界值是0.5,超過性能就會急劇下降。
-
【復習筆記】數據結構-檢索