雜湊表(hash table)是普通陣列概念的推廣,對於乙個比較小的規模的資料,我們對其儲存採用的是將其存在乙個等規模的陣列中,並且直接根據陣列下標對其進行定址,這被稱為直接定址法。
而當資料規模增大到一定程度時,我們採用直接定址法進行遍歷時會打打加重程式的時間複雜度,而一種理想的解決辦法就是根據資料的某一關鍵字(這裡假設資料元素含有其他衛星資料,這在實際問題中是很常見的)動態的分配儲存空間,將資料所需的儲存空間大小降低下來,這裡我們需要的演算法成為雜湊演算法h(key),一般認為他的結果為自然數,對映為陣列的下標,也即雜湊表槽的位置。
那麼接下來的問題就是——如何選擇乙個合理的雜湊演算法,是資料盡量均衡合理地分布,不發生衝突(collision)。
這裡介紹三種雜湊演算法。
除法雜湊法
h(k) = k mod 701,指的是關鍵字對槽數m取模,得到乙個較為均衡的排布在槽數內的雜湊值,這裡槽數的選擇不建議選擇2的整數次冪,會造成資料一定程度上的分布不均。
乘法雜湊法
h(k) = m * (k * a mod !),指的是關鍵字乘以乙個常數a(0 < a < 1),取小數部分乘以槽數。
全域法
全域法會綜合以上各種函式的特點,就像快速排序演算法採用隨機數確定乙個分界值,保證最壞情況不會總是發生,這裡全域法在接收到乙個關鍵字時,會隨機的從設計好的雜湊演算法中挑選乙個出來,使遇到兩個不同的關鍵字k,l時,h(k) == h(l)的概率不超過1/m(從m個槽中隨機選乙個的概率)。
然而無論是哪種演算法都無可避免的會遇到衝突問題,接下來兩種解決衝突問題的方法。
鏈結法
很簡單,就是將被雜湊到乙個槽中的資料都儲存在乙個鍊錶中,雙向鍊錶提高效率,將鍊錶的頭指標放在槽中。
開放定址法
首先引進裝載因子的概念,a = n /m,即每個槽中平均含有的資料數。
這種方法指的是每乙個資料都放在雜湊表的表項中,即每乙個槽中要麼有乙個元素,要麼為nil,當查詢某個元素時,要系統的檢查所有表項,直到找到需要的元素,或最終查明該元素不再表中。
int hash_insert(int t, int key)
while (i <= m);
return -1; //overflow
}
這裡雜湊演算法接受引數i,使之成為乙個二元對映,通過i的調節使其遍歷整個雜湊表來尋找空槽。模擬可以寫出刪除資料的函式。
完全雜湊法
在鏈結法中將雜湊到同乙個槽中的資料儲存在鍊錶中,而完全雜湊顧名思義則是將他們再存放在乙個雜湊表(第二級雜湊)中,這樣借助雜湊表的探查演算法,也許會獲得比搜尋鍊錶更高的效率。
最後當然是對雜湊表的定址,也叫探查(probe)方法了。
線性探查
給定乙個簡單的雜湊演算法h'(k),該探查採用的函式為h(k,i) = (h'(k) + i) mod m新增了隨機性,但是隨著被占用槽數的增加會出現一次群集現象。
二次探查
h(k,i) = (h'(k) + c1 * i + c2 * i ^ 2),這裡引進了i的二次項,使後續的探查位置多乙個偏移量,降低了一次群集,但是可能會導致另一種輕度的群集——二次群集,且受限於雜湊表的大小,c1 c2的大小受到限制。
雙重雜湊
雙重雜湊是用於開放定址法最好的探查方法之一,它需要兩個基礎的雜湊函式h1,h2,h(k,i) = (h1(k) + i * h2(k)) mod m,這裡偏移量不會像之前那兩種方法顯得「有跡可循」,它產生的排列具有隨機選擇排列的許多特性。
《演算法導論》雜湊表
雜湊表 hash table 是實現字典操作 查詢 插入 刪除 的有效資料結構,具有很高的查詢效率。一定情況下查詢元素的期望時間是o 1 優於鍊錶 o n 和直接定址的陣列 查詢也是o 1 相當。但當實際儲存的關鍵字數比可能的關鍵字總數小的時候,雜湊錶比陣列有效。一些記號 直接定址,關鍵字k存放在第...
演算法導論 雜湊表
include include includeusing namespace std const int length 6 待插入的數列長度 const int tablesize 11 雜湊表的容量 應該打大於數列長度以保證每個元素都有處可放 typedef struct hash hashtab...
演算法導論 雜湊表
華電北風吹 天津大學認知計算與應用重點實驗室 日期 2015 9 8 雜湊表 hash table 是一種支援高效插入,查詢,刪除操作的動態集合結構。並且在滿足一些合理假設下,這些操作的平均時間複雜度可以達到 1 這也是雜湊表能夠和二叉搜尋樹 紅黑樹 抗衡的乙個重要方面。一 直接定址表 當關鍵字集合...