hash概念
哈希算法將任意長度的二進制值映射爲較短的固定長度的二進制值,這個小的二進制值稱爲哈希值。哈希值是一段數據唯一且極其緊湊的數值表示形式。
搜索方法:可以進行少量的比較,1次或者2-3次從數據中得到要搜索的數據,是大量數據的搜索時間複雜度變成O(1)。
哈希函數hashfunc
可以通過哈希函數與存儲表中的元素建立一億映射的關係,可以通過此函數直接查找到該數據在哈希表中的位置。
插入元素
按照哈希函數的要求,講較長的數據通過哈希函數映射出較短的數據,以用來存儲該元素
搜索元素
通過需要搜索的元素的值來與哈希函數得到相應的映射數據,再根據哈希表和映射數據查找到該元素的位置。
常見的哈希函數
- 直接定址法:hash(key) = a*key +b ——以線性的方式直接定下地址
- 除留餘數法:hash(key) = key % n ——以餘數作爲哈希地址
- 平方取中法:比如說123數據,平方爲15129,取中間的12作爲哈希地址
- 隨機數法:hash(key) = random(key) random爲隨機數
- 數學分析法:存儲一些有規律的數據,比如說電話號碼。(先進行分析,在進行存儲)
哈希衝突
當採用除留餘數法進行哈希地址的取值時,先講4,5,6,7,9存入哈希表之後,在當存44的時候,發現44的地方已經被佔用,也就是說兩個數據所計算出的哈希地址相同,這樣就發生了哈希衝突
哈希衝突的解決辦法—閉散列
閉散列—線性探測
插入
簡單來說就是從發生衝突的地方向後查找,直到查找到可以存放位置,將其存放。如果查找到末尾還沒有適當位置,從0的位置繼續向後查找。
hash(key) = key % capacity
刪除
採用閉散列處理哈希衝突時,不能隨便物理刪除哈希表中已有的元素,若直接刪除元素會影響其他元素的搜索。比如刪除元素4,如果直接刪除掉,44查找起來可能會受影響。因此線性探測採用標記的僞刪除法來刪除一個元素。使用{EMPTY,EXIST,DELETE} 三個標誌來表示。
擴容
負載因子 = 填入表中的元素 / 哈希表的長度
當負載因子大於等於0.7 時,進行擴容,擴容是需要重新對哈希元素進行存儲。
閉散列—二次探測
顯然二次探測就是使用除留餘數法的餘數的二次方進行依次向後探測。
插入
和線性探測插入方式相同
刪除
和線性探測刪除方式相同
擴容
負載因子 一般爲0.5 時進行擴容。
閉散列代碼實現
開散列
以哈希桶的形式,也就是說,哈希表內部存放着鏈表,這樣可以使存放相同元素時。直接進行結點插入即可。
插入元素44的時候,哈希表的運行方式
刪除
直接將結點刪除即可
擴容
擴容時,也需要增大哈希桶的capacity,然後進行結點的重新排列。