散列表(HashTable)

HashSet

elem1,elem2,elem3...若是這一系列元素放到數組

  • 數組;查找O(n),插入O(n),刪除O(n)
  • 鏈表;查找o(n),插入o(1),刪除o(1)
  • HashSet;查找o(1),插入o(1),刪除o(1)

HashSet的實現原理

HashSet是經過數組查找複雜度爲0(1)實現的.
數組[hashfunction(elem)] = elem
clipboard.png緩存

徹底一致散列

每一個key生成的數組索引都是惟一的,且全部key生成的數組索引互不相同.服務器

非徹底一致散列

每一個key生成的數組索引都是惟一的,可是存在多個key生成的數組索是相同的狀況.
這時,就有了衝突,填充因子,重構哈希表等概念了.數據結構

[針對徹底一致散列的散列表的查找,插入,刪除過程]
利用元素進行哈希函數運算獲得數組的索引,而後把該元素放置到數組的索引單元中.
查找時,進行哈希計算迅速獲得元素的位置,若是該位置是null,代表無此元素;
插入時,通過哈希運算,找到存儲位置,檢查存儲位置若是爲null,則插入;若是不是null,代表已經存在,則出錯;因此將元素插入時,建議插入前先檢查是否已經存在待插入的元素.
刪除時同理,置爲null便可.函數

散列表

散列表,又稱字典,關聯數組。
一系列key-value形式的元素存放到某種數據結構中,能經過key迅速找到該數據對,如
電話薄中的手機號碼,[姓名,號碼]
(張三,18700977521)
(李四,15810387653)
(王二,13190008765)性能

實現方案

咱們先根據key生成key的hashset(數組a),而後額外建立一個數組b,數組b和數組a長度相同;假設key1在數組a中的索引是h(key1),那麼咱們就在數組b的h(key1)索引單元放置key1對應的value1.
當咱們查找某個key的value時,經過h(key)獲得其value在數組b中的索引.
當咱們判斷散列表是否已經包含key-value對時,取得key的hashset數組a,便可0(1)時間內實現判斷.
切記,數組a和數組b稱爲關聯數組,數組a是hashset,可是存放value的數組b並非hashset,它只是哥普通數組.spa

clipboard.png

散列表的應用案例

  1. 手機的聯繫人列表,能快速定位到某個朋友的手機號碼.
  2. 去重.將一堆元素逐個扔進散列表,重複的就丟棄,時間複雜度是o(n)
  3. 緩存.某一Twitter用戶對服務器發出請求,服務器計算獲得相應的界面,發送給用戶;對於登錄,註冊等界面,全部的用戶都是相同的,咱們能夠把這些固定不變的界面緩存下來,放入到一個字典中.

clipboard.png
4.dns解析.key是域名,value是ip索引

HashTable的瓶頸

碰撞

多個key通過哈希函數的計算獲得的數組索引值相同,稱爲碰撞.
解決碰撞的辦法有:(1)連接法 (2)開放地址法dns

裝載因子

裝載因子 = 散列表的元素數目 / 數組長度
當裝載因子 達到0.7時,建議延長散列表的長度,不至於使數組每一個單元連接的元素數目太長,下降了散列表的性能.ip

證實哈希表的時間複雜度是O(1)

假設n個元素,數組長度是m,哈希函數具備良好的隨機性,那麼咱們查找某個元素的時間複雜度是O(n/m),同時咱們會在填充因子大於0.7時擴充數組的長度,即,n和m是線性關係,m = kn(k是常數),因此有 O(n/m) = O(n / kn) = O(1/k) = O(1).

HashTable的最壞狀況

HashTable容許出現碰撞,可是若是採用的哈希函數極其噁心,把不少key都連接到數組的相同索引,這時候查找的時間複雜度是O(n).一個好的哈希函數是HashTable的命,直接決定散列表的性能.一個好的哈希函數應該讓每一個key獨立且隨機的生成索引,從而儘量的逼近這樣的一種狀態:數組的絕大部分單元都連接了元素,且每一個單元連接的元素數目大體相等.最佳狀態稱爲徹底一致散列,即數組的每一個單元都存放一個元素!

相關文章
相關標籤/搜索