揭開散列表的神祕面紗

散列函數 會把一個很大的輸入空間映射到一個較小的輸出空間。可以用散列函數把大輸入空間中的鍵轉換爲小輸出空間中的整數索引。

因爲可能的輸出空間比可能的輸入空間小,散列函數實際上是一個多對一的映射,也就是說,不同的輸入可能會被映射到相同的輸出。如果兩個輸入被映射到同一個輸出,我們就說發生了碰撞。一個優秀的散列函數會產生一個均勻分佈,也就是說,每個輸出出現的可能性都相同,從而最小化產生碰撞的可能性。

設計一個優秀的散列函數是非常具有挑戰性的。問題在於如何將具有預期分佈的輸入映射到均勻分佈的輸出上。

基礎思想是用一個散列桶列表來表示intDict類的實例,每個桶是一個鍵值對列表。由於每個通都是一個列表,我們可以將產生碰撞的值都存儲到這個列表中。

散列表的工作方式如下:實例變量buckets被初始化爲一個列表,包含numBuckets個空列表。如果要存儲或者查找鍵爲dictKey的元素,我們使用散列函數%把dictKey轉換成一個整數,然後用它索引關聯到dictKey的散列桶。接着線性搜索這個桶(它就是一個列表)來判斷是否有鍵爲dictKey的元素。

如果我們執行的是查找操作並且有對應的元素,那就返回對應的值。如果沒有對應的元素,我們返回None。如果我們執行的是存儲操作並且有對應的元素,我們會替換它的值;如果沒有對應的元素,我們會向這個桶中添加一個新元素。

除此之外,還有很多處理碰撞的方法,有些比使用列表更加高效。但是這可能是最簡單的方法,並且在散列表足夠大而且散列函數能實現近似均勻分佈的情況下表現很好。

注意,__str__方法會生成字典的一個字符串形式,並且和元素添加到D中的順序無關,而是根據鍵的散列結果來排序。這解釋了爲什麼我們不應當相信字典類型對象的鍵的順序。


wKiom1imdKSzJRfSAAHvru0Bn_o789.png-wh_50

以上內容來自書籍 《編程導論》美·谷泰格。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章