1.哈希查找
(1)什麼是哈希表(Hash)
咱們使用一個下標範圍比較大的數組來存儲元素。能夠設計一個函數(哈希函數, 也叫作散列函數),使得每一個元素的關鍵字都與一個函數值(即數組下標)相對應,因而用這個數組單元來存儲這個元素;也能夠簡單的理解爲,按照關鍵字爲每個元素"分類",而後將這個元素存儲在相應"類"所對應的地方。可是,不可以保證每一個元素的關鍵字與函數值是一一對應的,所以極有可能出現對於不一樣的元素,卻計算出了相同的函數值,這樣就產生了"衝突",換句話說,就是把不一樣的元素分在了相同的"類"之中。後面咱們將看到一種解決"衝突"的簡便作法。
總的來講,"直接定址"與"解決衝突"是哈希表的兩大特色。
(2)什麼是哈希函數
[1]哈希函數的規則是:經過某種轉換關係,使關鍵字適度的分散到指定大小的的順序結構中,越分散,則之後查找的時間複雜度越小,空間複雜度越高。
[2]算法思想:哈希的思路很簡單,若是全部的鍵都是整數,那麼就可使用一個簡單的無序數組來實現:將鍵做爲索引,值即爲其對應的值,這樣就能夠快速訪問任意鍵的值。這是對於簡單的鍵的狀況,咱們將其擴展到能夠處理更加複雜的類型的鍵。
[3]算法流程:
1)用給定的哈希函數構造哈希表;
2)根據選擇的衝突處理方法解決地址衝突;
常見的解決衝突的方法:拉鍊法和線性探測法。
3)在哈希表的基礎上執行哈希查找。
哈希表是一個在時間和空間上作出權衡的經典例子。若是沒有內存限制,那麼能夠直接將鍵做爲數組的索引。那麼全部的查找時間複雜度爲O(1);若是沒有時間限制,那麼咱們可使用無序數組並進行順序查找,這樣只須要不多的內存。哈希表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只須要調整哈希函數算法便可在時間和空間上作出取捨。
(3)複雜度分析:
單純論查找複雜度:對於無衝突的Hash表而言,查找複雜度爲O(1)(注意,在查找以前咱們須要構建相應的Hash表)。
使用Hash,咱們付出了什麼?
咱們在實際編程中存儲一個大規模的數據,最早想到的存儲結構可能就是map,也就是咱們常說的KV pair,常常使用java的博友可能更有這種體會。使用map的好處就是,咱們在後續處理數據處理時,能夠根據數據的key快速的查找到對應的value值。map的本質就是Hash表,那咱們在獲取了超高查找效率的基礎上,咱們付出了什麼?
Hash是一種典型以空間換時間的算法,好比原來一個長度爲100的數組,對其查找,只須要遍歷且匹配相應記錄便可,從空間複雜度上來看,假如數組存儲的是byte類型數據,那麼該數組佔用100byte空間。如今咱們採用Hash算法,咱們前面說的Hash必須有一個規則,約束鍵與存儲位置的關係,那麼就須要一個固定長度的hash表,此時,仍然是100byte的數組,假設咱們須要的100byte用來記錄鍵與位置的關係,那麼總的空間爲200byte,並且用於記錄規則的表大小會根據規則,大小多是不定的。
java