【算法】散列表(hash table)

爲何散列表會出現

  • 場景:若是超市買東西結帳的時候,售貨員在一個本子裏查找價格
  • 若是是有序的(二分查找)還好,時間是 O(logn),若是是無序(簡單查找)的話,那就是 O(n)
  • 若是直接有一個 O(1)的查找速度就行了

散列函數

將輸入映射到數字數組

  • 一致性:輸入 apple 時獲得的是 4,那麼每次輸入 apple 都必須是 4
  • 不一樣性:不一樣的輸入將獲得不一樣的輸出。若是輸入 apple 和 yoki 都獲得 4,那麼這是一個很差的散列函數。

創造散列表

結合散列函數和數組瀏覽器

  • 建立一個空數組
  • apple 輸入到散列函數,輸出 3,而後把 apple 的價格存儲到數組索引 3
  • 接着各個類推,知道存完數組
  • 而後咱們要找 apple 的價格,就把 apple 輸入交給散列函數,獲得 3 去數組裏面找

散列表的經典應用

查找,防止重複,用於緩存緩存

查找

  • 被用於大海撈針的查找
  • 這個就不用細說了,相似的有 dns 解析

防止重複

場景:負責一個投票站,每一個人只能投一票,如何避免重複投票服務器

  • 有一個方法是:有人來投票,就將它記錄在一個投票名單裏面,而後接下來的人都遍歷這個投票名單,若是有就不能投票,可是這樣就列表會愈來愈長,就會變慢
  • 另一種就是散列表,超快

緩存

  • 瀏覽器緩存的數據存儲在散列表裏面
  • 若是訪問 facebook 的頁面,會先檢查散列表中是否存儲了該頁面
  • 若是不在緩存中,纔去訪問服務器,而後把數據放到緩存裏,這樣下次有人訪問就能夠直接命中緩存

衝突

事實上不可能不一樣的輸入都能得到不一樣的值app

  • 假設有一個數組包含 26 個位置,而咱們使用的散列函數很是簡單,按照字母表順序分配位置
  • apple 第一個,bear 第二個,接下來來了一個 banana,理應分到第二個,可是這個時候第二個位置已是 bear 了
  • 這個就叫衝突,解決衝突的辦法有不少,簡單的就是在這個衝突的位置存儲一個鏈表,bear 末尾的指針指向 banana
  • 因此散列函數很重要,好的散列函數將 key 均勻的映射到散列表的不一樣位置

如何避免衝突

  • 較低的填裝因子
    • 散列表包含的元素數:位置總數就是填裝因子
    • 越小越好,滿了只能調整長度,換一個更長的數組
    • 一個不錯的經驗規則就是,一旦填裝因子大於 0.7,那麼就要調整散列表的長度
  • 良好的散列函數
    • SHA 函數

散列表性能如何

平均狀況

  • 查找,插入,刪除都是 O(1),常量時間

最糟糕狀況

  • 查找,插入,刪除都是 O(n),線性時間

爲何會有兩種狀況,這是由於有了衝突可能會靠鏈表解決,n 個長度的鏈表,最好狀況下沒有衝突,就常量時間 )函數

相關文章
相關標籤/搜索