一、直接映射表
程序員
查找數據時,直接定位,時間複雜度爲:O(1);算法
侷限性:浪費大量的內存空間;ide
二、哈希表函數
(1)、用一個哈希函數Hash()來隨機映射那些鍵;spa
抽象模型blog
(2)、哈希衝突時:ip
i、鏈地址法,時間複雜度最壞:O(n);內存
簡單均勻哈希的時間複雜度:O(1+a);a:裝載因子get
哈希函數的選取:除留餘數法;it
ii、開放尋址法,沒有鏈表;
利用屢次哈希函數,探測空的位置,直到找到一個能夠存放元素的位置便可;探查序列很重要!!!
插入、查詢就根據探查序列比較簡單,刪除比較難作;
探測序列:a、線性探測:一個挨一個位置的探測,往下掃描;
探測序列:b、二次哈希:2個哈希函數的和掃描;
哈希表越滿,其探查效率越低;
三、哈希表溢出,動態哈希怎麼實現?
i、首先申請一個原哈希表2倍大的空間;
ii、在將舊有元素移到新的哈希表空間中;
iii、在釋放原有空間;
平攤分析的思想:
一個插入的平均代價時間複雜度:O(1);
n個元素的插入時間複雜度是:O(n);
四、哈希函數的全部鍵映射同一個槽,此時查詢效率極爲低下。
(1)、問題關鍵:選擇哈希函數,要隨機選擇,與輸入的哈希運算的鍵保存獨立,程序員自己也不能肯定在實際運行時會用到哪個哈希函數,沒法預測隨機數的輸出;----->全域哈希
(2)、全域哈希解決的問題:全部鍵都相同,此時隨機選擇哈希函數將會使其映射到不一樣的槽中;
哈希函數集H中隨機地選擇函數h,均勻的分佈在哈希表中;
(3)、全域哈希的構造:
i、槽的總數爲m = 質數時成立,k = <k_0,k_1,.....,k_r>把任意的鍵分解爲r+1位,能夠把k當作k_0,k_1......k_r(k_i >= 0 && k_i <= m-1),k用"m進制"來表示;k不斷除m,取餘在除(進制轉換法)
ii、構造一個a = <a0,a1,a2....ar>,隨機地從(0,1,2,....m-1)中選取元素分配到a集合中;
哈希函數集:k x a,k中的每一項和a中的每一項相乘,再把乘積所有加起來,在對m取餘,就獲得分配的槽數;哈希函數集的大小:m^(r+1);
(4)、全域哈希是用隨機函數的思想,可是有很小很小的機率仍是會衝突的,解決方案:徹底哈希;
五、徹底哈希
使用二級結構,在每一級都會用全域哈希,第一級可能會有衝突,可是第二級就沒有了;
(1)、算法模型
(2)、算法分析:
時間複雜度:O(1);
所需的存儲空間爲:O(n);