首先看看散列算法是什麼。
散列函數或散列算法,又稱哈希函數,英語:Hash Function,是一種從任何一種數據中建立小的數字「指紋」
的方法。散列函數把消息或數據壓縮成摘要,使得數據量變小,將數據的格式固定下來。該函數將數據打亂混合,從新
建立一個叫作散列值的指紋。散列值一般用來表明一個短的隨機字母和數字組成的字符串。
全部散列函數都有以下一個基本特性:若是兩個散列值是不相同的(根據同一函數),那麼這兩個散列值的原
始輸入也是不相同的。這個特性是散列函數具備肯定性的結果,具備這種性質的散列函數稱爲單向散列函數。但另外一方
面,散列函數的輸入和輸出不是惟一對應關係的,若是兩個散列值相同,兩個輸入值極可能是相同的。但也可能不一樣,
這種狀況稱爲「散列碰撞」,這一般是兩個不一樣長度的散列值,刻意計算出相同的輸出值。html
散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它
經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫作散列函數,存放記錄的數組叫
作散列表。算法
首先Dictionary<TKey,TValue>是泛型版本的Hashtable,二者都是使用hashtable實現的
(http://en.wikipedia.org/wiki/Hashtable)。其最大的不一樣在於處理衝突上。
Hashtable採用的是直接散列或者在散列的方式,簡而言之就是,發生衝突的時候,經過查找下一個空位置以解
決衝突。而當元素愈來愈多的時候(接近)存儲容量的時候,衝突的機率就極大的增長了,所以能夠在某個界限的時候
擴容解決這個問題。(當咱們知道元素大概數量是,咱們也能夠設置容量)。
擴容是個耗時很是驚人的內部操做,Hashtable 之因此寫入效率僅爲讀取效率的 1/10 數量級, 頻繁的擴容是一個因素
。當進行擴容時,散列表內部要從新 new 一個更大的數組,而後把原來數組的內容拷貝到新數組,並進行從新散列。如
何 new 這個更大的數組也有講究。散列表的初始容量通常來說是個素數。當擴容時,新數組的大小會設置成原數組雙倍
大小的相近的一個素數。爲了不生成素數的額外開銷,.NET 內部有一個素數數組,記錄了經常使用到的素數(這裏就不列
出,下面文章中能夠看到)。
Dictionary<TKey,TValue>使用的則是鏈表式的衝突解決辦法,就是將衝突元素以鏈表的方式存儲與key關聯。
這樣就避免了擴容問題。數組
這裏有幾篇hashtable數據結構的文章
(http://www.cnblogs.com/lucifer1982/archive/2008/06/18/1224319.html)
(http://www.cnblogs.com/lucifer1982/archive/2008/07/03/1234431.html)
(http://blog.csdn.net/chartnie/article/details/6790521)
(http://blogs.msdn.com/b/kcwalina/archive/2004/08/06/210297.aspx)數據結構