當前位置:成語大全網 - 英語詞典 - python dict 實現原理 2019-04-17

python dict 實現原理 2019-04-17

dict對象是Python中壹個原始的數據類型,按照鍵值對的方式存儲,中文名為字典,其通過鍵名查找對應的值有很高的效率,時間復雜度在常數級別O(1)。Python dict的底層是依靠哈希表(Hash Table)進行實現的,使用開放地址法解決沖突。所以其查找的時間復雜度會是O(1),why?

哈希表是key-value類型的數據結構,通過關鍵碼值直接進行訪問。通過散列函數進行鍵和數組的下標映射從而決定該鍵值應該放在哪個位置,哈希表可以理解為壹個鍵值需要按壹定規則存放的數組,而哈希函數就是這個規則。

算法中時間和空間是不能兼得的,哈希表就是壹種用合理的時間消耗去減少大量空間消耗的操作,這取決於具體的功能要求。

創建壹個數組,數組下標是索引號,數組中的值是要獲得的數據,這樣只需要O(1)的時間復雜度就可以完成操作,但是擴展性不強,有以下兩個方面的考慮:

-1- 新添加的元素超出數組索引範圍,這就需要重新申請數組進行遷移操作。

-2- 假設壹種極端的情況:只存在兩個元素,索引號分別是1和100000000001,按照先前的設計思路,會浪費很大的存儲空間。

會不會存在壹個方法,為已有的索引創建新的索引,通過壓縮位數,讓新索引可以和原有的大範圍的稀疏索引進行壹壹對應,新索引所需要的存儲空間要大大減小,這就是哈希思想。

上面的例子中哈希函數的設計很隨意,但是從這個例子中我們也可以得到信息:

哈希函數就是壹個映射,因此哈希函數的設定很靈活,只要使得任何關鍵字由此所得的哈希函數值都落在表長允許的範圍之內即可;

因為新的索引對舊的索引進行了空間上的壓縮,所以不可能所有的輸入都只對應唯壹壹個輸出,也就是哈希函數式有可能發生沖突的,哈希函數不可能做成壹對壹的映射關系,其本質是壹個多對壹的映射。

直接定址法:很容易理解,key=Value+C; 這個“C”是常量。Value+C其實就是壹個簡單的哈希函數。

除法取余法: 很容易理解, key=value%C;解釋同上。

數字分析法:這種蠻有意思,比如有壹組value1=112233,value2=112633,value3=119033,針對這樣的數我們分析數中間兩個數比較波動,其他數不變。那麽我們取key的值就可以是key1=22,key2=26,key3=90。

平方取中法。此處忽略,見名識意。

折疊法:這種蠻有意思,比如value=135790,要求key是2位數的散列值。那麽我們將value變為13+57+90=160,然後去掉高位“1”,此時key=60,哈哈,這就是他們的哈希關系,這樣做的目的就是key與每壹位value都相關,來做到“散列地址”盡可能分散的目地。

當兩個不同的數據元素的哈希值相同時,就會發生沖突。解決沖突常用的手法有2種:

開放地址法:

如果兩個數據元素的哈希值相同,則在哈希表中為後插入的數據元素另外選擇壹個表項。當程序查找哈希表時,如果沒有在第壹個對應的哈希表項中找到符合查找要求的數據元素,程序就會繼續往後查找,直到找到壹個符合查找要求的數據元素,或者遇到壹個空的表項。

鏈接法:

將哈希值相同的數據元素存放在壹個鏈表中,在查找哈希表的過程中,當查找到這個鏈表時,必須采用線性查找方法。

python的dict采用了哈希表,最低能在 O(1)時間內完成搜索,在發生哈希沖突的時候采用的是開放尋址法。java的HashMap也是采用了哈希表實現,但是在發生哈希沖突的時候采用的是鏈接法。