散列表 又叫 哈希表 (hash table)。經過訪問key而直接訪問存儲的value值。它的key - value之間存在一個映射函數,咱們能夠經過key值和「看不到」的映射函數(散列函數)訪問對應的value值。這加快了查找的速度!存放記錄的數組稱作散列表。散列方法不一樣於順序查找、二分查找、二叉排序樹及B-樹上的查找。它不以關鍵字的比較爲基本操做,採用直接尋址技術 (就是說,它是直接經過key映射[映射函數,實現的方式有多種] 到內存地址上去的)。在理想狀況下,無須任何比較就能夠找到待查關鍵字,查找的指望時間爲O(1)(面試的時候犯了這個錯誤)。php
舉個形象的例子來講:爲了查找電話簿中某人的號碼,能夠建立一個按照人名首字母順序排列的表(即創建人名到首字母
的一個函數關係),在首字母爲W的表中查找「王」姓的電話號碼,顯然比直接查找就要快得多。這裏使用人名做爲關鍵字,「取首字母」是這個例子中散列函數的函數法則
,存放首字母的表對應散列表。關鍵字和函數法則理論上能夠任意肯定。[維基百科]面試
散列表
設全部可能出現的關鍵字集合記爲U(簡稱全集)。實際發生(即實際存儲)的關鍵字集合記爲K(|K|比|U|小得多)。
散列方法是使用函數h將U映射到表T[0..m-1]的下標上(m=O(|U|))。這樣以U中關鍵字爲自變量,以h爲函數的運算結果就是相應結點的存儲地址。從而達到在O(1)時間內就可完成查找。
其中:
① h:U→{0,1,2,…,m-1} ,一般稱h爲散列函數(Hash Function)。散列函數h的做用是壓縮待處理的下標範圍,使待處理的|U|個值減小到m個值,從而下降空間開銷。
② T爲散列表(Hash Table)。
③ h(Ki)(Ki∈U)是關鍵字爲Ki結點存儲地址(亦稱散列值或散列地址)。
④ 將結點按其關鍵字的散列地址存儲到散列表中的過程稱爲散列(Hashing)數組
咱們基本知道了value和key之間存在一個映射關係h,簡單的表示爲 value = h(key)。 咱們會有疑問,函數以容許多對一出現的,也就是說,當多個key對應一個value時怎麼辦?安全
這就是散列表中的衝突。分佈式
散列表的衝突現象
(1)衝突
兩個不一樣的關鍵字,因爲散列函數值相同,於是被映射到同一表位置上。該現象稱爲衝突(Collision)或碰撞。發生衝突的兩個關鍵字稱爲該散列函數的同義詞(Synonym)。
【例】上圖中的k2≠k5,但h(k2)=h(k5),故k2和K5所在的結點的存儲地址相同。
(2)安全避免衝突的條件
最理想的解決衝突的方法是安全避免衝突。要作到這一點必須知足兩個條件:
①其一是|U|≤m
②其二是選擇合適的散列函數。
這隻適用於|U|較小,且關鍵字均事先已知的狀況,此時通過精心設計散列函數h有可能徹底避免衝突。
(3)衝突不可能徹底避免
一般狀況下,h是一個壓縮映像。雖然|K|≤m,但|U|>m,故不管怎樣設計h,也不可能徹底避免衝突。所以,只能在設計h時儘量使衝突最少。同時還須要肯定解決衝突的方法,使發生衝突的同義詞可以存儲到表中。
函數
構造散列函數spa
(直接複製的維基百科,詳細可參見[1]) 散列函數能使對一個數據序列的訪問過程更加迅速有效,經過散列函數,數據元素將被更快定位。設計
散列表的查找過程基本上和造表過程相同。一些關鍵碼可經過散列函數轉換的地址直接找到,另外一些關鍵碼在散列函數獲得的地址上產生了衝突,須要按處理衝突的方法進行查找。在介紹的三種處理衝突的方法中,產生衝突後的查找仍然是給定值與關鍵碼進行比較的過程。因此,對散列表查找效率的量度,依然用平均查找長度來衡量。xml
查找過程當中,關鍵碼的比較次數,取決於產生衝突的多少,產生的衝突少,查找效率就高,產生的衝突多,查找效率就低。所以,影響產生衝突多少的因素,也就是影響查找效率的因素。影響產生衝突多少有如下三個因素:blog
參考:【1】維基百科 散列表 http://zh.wikipedia.org/zh-cn/%E5%93%88%E5%B8%8C%E8%A1%A8
【2】維基百科 分佈式散列表 http://zh.wikipedia.org/zh-cn/%E5%88%86%E6%95%A3%E5%BC%8F%E9%9B%9C%E6%B9%8A%E8%A1%A8