![](/img/trans.png)
[英]Dictionary(TKey, TValue) GetHashCode and Equals - How do they work?
[英]How does the process of hashing work in Dictionary<TKey, TValue>
字典中的哈希處理如何工作? 我讀到使用字典可以更快地查找。 但是不明白怎么辦? 哈希和映射到索引如何發生? 找不到任何好的參考。
編輯:如何從哈希函數的結果中獲取存儲對象的實際內存位置?
哈希表或字典是一種存儲鍵-值對的數據結構。 哈希表的優點在於,給定鍵找到對應的值非常快。 簡化后,在哈希表中查找鍵值對的時間並不取決於表的大小。 將其與將鍵值對存儲在列表或數組中進行比較。 要查找鍵值對,您必須從頭開始搜索列表,直到找到匹配的鍵。 列表越長,找到鍵值對所需的時間就越多。 使用big-O表示法可以說,在哈希表中查找鍵的順序為O(1),而通過線性搜索在列表中查找鍵的順序為O(N)(簡化)。
要將鍵值對插入哈希表中,您首先必須計算鍵的哈希碼。 在.NET中,所有對象都有一個名為GetHashCode
的方法,該方法返回該特定對象的哈希碼(32位整數)。 相等的對象返回相同的哈希碼很重要,但是如果不同的對象返回不同的哈希碼,這也非常有用。 注意不要誤認為不同的對象不能返回相同的哈希碼-它們可以,但是會導致沖突 (請參閱下文)。
例如,考慮兩個字符串的哈希碼:
"Boo" 0x598FD95A "Foo" 0x598FD8DE
即使字符串非常相似,它們也具有不同的哈希碼。
我在這里簡化一些事情,以關注哈希表的重要方面,因此,現在讓我們說,Internally Dictionary<TKey, TValue>
將鍵值對存儲在數組中。 要在將鍵值對存儲在此數組中的索引中找到索引,您必須以數組大小為模來計算鍵的哈希碼。 假設數組的大小為5:
Index("Boo") = 0x598FD95A % 5 = 4 Index("Foo") = 0x598FD8DE % 5 = 0
這導致此內部哈希表數組:
+---+---------+ | 0 | "Foo" | +---+---------+ | 1 | (empty) | +---+---------+ | 2 | (empty) | +---+---------+ | 3 | (empty) | +---+---------+ | 4 | "Boo" | +---+---------+
在哈希表中查找條目非常快。 您只需要以內部數組的大小為模來計算鍵的哈希碼,然后在該索引處檢索字符串。
現在考慮鍵“ Zoo”:
Index("Zoo") = 0x598FDC62 % 5 = 0
它具有與鍵“ Foo”相同的索引。 這導致所謂的碰撞 。 哈希表的正確實現將必須處理沖突,並且這樣做有不同的策略 。 同樣,隨着內部數組的填充,數組中的空白元素將越來越少,從而導致沖突數量增加。 負載系數是內部陣列中已用元素與總元素之間的比率。 在上面的示例中,負載系數為2/5 = 0.4。 當負載因子超過特定閾值時,大多數哈希表實現都會增加內部數組的大小。
如果您想更多地了解其中一些概念,則必須研究與其他答案相關聯的一些更全面的資源。
詞典中的哈希處理使用一種稱為鏈接的技術。 通過鏈接,輔助數據結構可用於保留任何沖突。 具體來說,字典中的每個廣告位都有一個映射到存儲桶的元素數組。 在發生碰撞的情況下,碰撞元素位於鏟斗列表的前面。
有關更多詳細信息,請參見MSDN上的這篇文章。
通常,通過獲取哈希值%數組大小,可能會產生沖突。
正如我試圖在回答其他問題時所解釋的那樣,字典使用哈希鍵進行查找。 因此,如果您有一個自定義對象類型作為鍵,那么一切都取決於自定義對象的GetHashCode()
實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.