咱們先看Hashtable。html
MSDN的解釋:表示鍵/值對的集合,這些鍵/值對根據鍵的哈希代碼進行組織。算法
Hash算法是把任意長度的輸入(又叫作預映射, pre-image),經過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間一般遠小於輸入的空間,不 同的輸入可能會散列成相同的輸出,而不可能從散列值來惟一的肯定輸入值。 數組
Hashtable 對象由包含集合元素的存儲桶組成。存儲桶是 Hashtable 中各元素的虛擬子組,與大多數集合中進行的搜索和檢索相比,存儲桶 可令搜索和檢索更爲便捷。每一存儲桶都與一個哈希代碼關聯,該哈希代碼是使用哈希函數生成的並基於該元素的鍵。數據結構
Hashtable 類默認的裝填因子是 1.0,但實際上它默認的裝填因子是 0.72。全部從構造函數輸入的裝填因子,Hashtable 類內部都會將其乘以0.72。這是一個要求苛刻的數字, 某些時刻將裝填因子增減 0.01, 可能你的 Hashtable 存取效率就提升或下降了 50%,其緣由是裝填因子決定散列表容量,而散列表容量又影響 Key 的衝突概率,進而影響性能。0.72 是 Microsoft通過大量實驗得出的一個比較平衡的值。函數
咱們看Hashtable的一些源碼:性能
Hashtable 擴容是個耗時很是驚人的內部操做,它之因此寫入效率僅爲讀取效率的 1/10 數量級,頻繁的擴容是一個因素。當進行擴容時,散列表內部要從新 new 一個更大的數組,而後把原來數組的內容拷貝到新數組,並進行從新散列。如何 new這個更大的數組也有講究。散列表的初始容量通常來說是個素數。當擴容時,新數組的大小會設置成原數組雙倍大小的相近的一個素數。測試
HashTable數據結構存在問題:空間利用率偏低、受填充因子影響大、擴容時全部的數據須要從新進行散列計算。雖然Hash具備O(1)的數據檢索效率,但它空間開銷卻一般很大,是以空間換取時間。因此Hashtable適用於讀取操做頻繁,寫入操做不多的操做類型。spa
而Dictionary<K, V> 也是用的Hash算法,經過數組實現多條鏈式結構。不過它是採用分離連接散列法。採用分離連接散列法不受到裝填因子的影響,擴容時原有數據不須要從新進行散列計算。code
採用分離連接法的 Dictionary<TKey, TValue> 會在內部維護一個鏈表數組。對於這個鏈表數組 L0,L1,...,LM-1, 散列函數將告訴咱們應當把元素 X 插入到鏈表的什麼位置。而後在 find 操做時告訴咱們哪個表中包含了 X。 這種方法的思想在於:儘管搜索一個鏈表是線性操做,但若是表足夠小,搜索很是快(事實也的確如此,同時這也是查找,插入,刪除等操做並不是老是 O(1) 的緣由)。特別是,它不受裝填因子的限制。
這種狀況下,常見的裝填因子是 1.0。更低的裝填因子並不能明顯的提升性能,但卻須要更多的額外空間。 htm
Dictionary的插入算法:一、計算key的hash值,而且找到buckets中目標桶的鏈首索引,二、從鏈上依次查找是否key已經保存,三、若是沒有的話,判斷是否存在freeList,四、若是存在freeList,從freeList上摘下結點保存數據,不然追加在count位置上。
buckets數組保存全部數據鏈的鏈首,Buckets[i]表示在桶i中數據鏈的鏈首元素。entries結構體數組用於保存實際的數據,經過next值做爲鏈式結構的向後索引。刪除的數據空間會被串入到freeList鏈表的首部,當再次插入數據時,會首先查找freeList鏈表,以提升查找entries中空閒數據項位置的效率。在枚舉器中,枚舉順序爲entries數組的下標遞增順序。
而SortedDictionary,MSDN是這樣描述的:
SortedDictionary<(Of <(TKey, TValue>)>) 泛型類是檢索運算複雜度爲 O(log n) 的二叉搜索樹,其中 n 是字典中的元素數。就這一點而言,它與 SortedList<(Of <(TKey, TValue>)>) 泛型類類似。這兩個類具備類似的對象模型,而且都具備 O(log n) 的檢索運算複雜度。這兩個類的區別在於內存的使用以及插入和移除元素的速度:
SortedDictionary<K, V>是按照K有序排列的(K, V)數據結構,以紅黑樹做爲內部數據結構對K進行排列保存– TreeSet<T>,紅黑樹是一棵二叉搜索樹,每一個結點具備黑色或者紅色的屬性。它比普通的二叉搜索樹擁有更好的平衡性。2-3-4樹是紅黑樹在「理論」上的數據結構。
2-3-4樹插入算法:相似於二叉搜索樹的插入(插入數據插入到樹的葉子結點) ,若是插入位置是2-結點或者3-結點,那麼直接插入到當前結點,若是插入位置是4-結點,須要將當前的4-結點進行拆分,而後再執行後繼的插入操做。
咱們來測試一下Hashtable、Dictionary和SortedDictionary的插入和查找性能。
最終結果如圖:
(原文:http://www.cnblogs.com/moozi/archive/2010/05/23/1741980.html)