089 字典的底層原理

2021-09-24 12:03:05 字數 2345 閱讀 9389

字典也被稱為關聯陣列,還稱為雜湊陣列等。也就是說,字典也是乙個陣列,但陣列的索引是鍵經過雜湊函式處理後得到的雜湊值。雜湊函式的目的是使鍵均勻地分布在陣列中,並且可以在記憶體中以o(1)的時間複雜度進行定址,從而實現快速查詢和修改。雜湊表中雜湊函式的設計困難在於將資料均勻分布在雜湊表中,從而儘量減少雜湊碰撞和衝突。由於不同的鍵可能具有相同的雜湊值,即可能出現衝突,高階的雜湊函式能夠使衝突數目最小化。python中並不包含這樣高階的雜湊函式,幾個重要(用於處理字串和整數)的雜湊函式是常見的幾個型別。通常情況下建立雜湊表的具體過程如下:

資料新增:把key通過雜湊函式轉換成乙個整型數字,然後就將該數字對陣列長度進行取餘,取餘結果就當作陣列的下標,將value儲存在以該數字為下標的陣列空間裡。

資料查詢:再次使用雜湊函式將key轉換為對應的陣列下標,並定位到陣列的位置獲取value。

雜湊函式就是乙個對映,因此雜湊函式的設定很靈活,只要使得任何關鍵字由此所得的雜湊函式值都落在表長允許的範圍之內即可。本質上看雜湊函式不可能做成乙個一對一的對映關係,其本質是乙個多對一的對映,這也就引出了下面乙個概念–雜湊衝突或者說雜湊碰撞。雜湊碰撞是不可避免的,但是乙個好的雜湊函式的設計需要盡量避免雜湊碰撞。

python2中使用使用開放位址法解決衝突。

cpython使用偽隨機探測(pseudo-random probing)的雜湊表(hash table)作為字典的底層資料結構。由於這個實現細節,只有可雜湊的物件才能作為字典的鍵。字典的三個基本操作(新增元素,獲取元素和刪除元素)的平均事件複雜度為o(1)。

python中所有不可變的內建型別都是可雜湊的。

可變型別(如列表,字典和集合)就是不可雜湊的,因此不能作為字典的鍵。

開放定址法中,所有的元素都存放在雜湊表裡,當產生雜湊衝突時,通過乙個探測函式計算出下乙個候選位置,如果下乙個獲選位置還是有衝突,那麼不斷通過探測函式往下找,直到找個乙個空槽來存放待插入元素。

開放位址的意思是除了雜湊函式得出的位址可用,當出現衝突的時候其他的位址也一樣可用,常見的開放位址思想的方法有線性探測再雜湊,二次探測再雜湊等,這些方法都是在第一選擇被占用的情況下的解決方法。

這個方法是按順序規定多個雜湊函式,每次查詢的時候按順序呼叫雜湊函式,呼叫到第乙個為空的時候返回不存在,呼叫到此鍵的時候返回其值。

將所有關鍵字雜湊值相同的記錄都存在同一線性鍊錶中,這樣不需要占用其他的雜湊位址,相同的雜湊值在一條鍊錶上,按順序遍歷就可以找到。

一般情況下,處理衝突方法相同的雜湊表,其平均查詢長度依賴於雜湊表的裝填因子。雜湊表的裝填因子定義為表中填入的記錄數和雜湊表長度的比值,也就是標誌著雜湊表的裝滿程度。直**來,α越小,發生衝突的可能性就越小,反之越大。一般0.75比較合適,涉及數學推導。

在python中乙個key-value是乙個entry,

entry有三種狀態。

unused: me_key == me_value == null

unused是entry的初始狀態,key和value都為null。插入元素時,unused狀態轉換成active狀態。這是me_key為null的唯一情況。

active: me_key != null and me_key != dummy 且 me_value != null

插入元素後,entry就成了active狀態,這是me_value唯一不為null的情況,刪除元素時active狀態刻轉換成dummy狀態。

dummy: me_key == dummy 且 me_value == null

此處的dummy物件實際上乙個pystringobject物件,僅作為指示標誌。dummy狀態的元素可以在插入元素的時候將它變成active狀態,但它不可能再變成unused狀態。

為什麼entry有dummy狀態呢?這是因為採用開放定址法中,遇到雜湊衝突時會找到下乙個合適的位置,例如某元素經過雜湊計算應該插入到a處,但是此時a處有元素的,通過探測函式計算得到下乙個位置b,仍然有元素,直到找到位置c為止,此時abc構成了探測鏈,查詢元素時如果hash值相同,那麼也是順著這條探測鏈不斷往後找,當刪除探測鏈中的某個元素時,比如b,如果直接把b從雜湊表中移除,即變成unused狀態,那麼c就不可能再找到了,因為ac之間出現了斷裂的現象,正是如此才出現了第三種狀態---dummy,dummy是一種類似的偽刪除方式,保證探測鏈的連續性。

提示一般情況下普通的順序表陣列儲存結構也可以認為是簡單的雜湊表,雖然沒有採用雜湊函式(取餘),但同樣可以在o(1)時間內進行查詢和修改。但是這種方法存在兩個問題:擴充套件性不強;浪費空間。

set集合和dict一樣也是基於雜湊表的,只是他的表元只包含值的引用而沒有對鍵的引用,其他的和dict基本上是一致的,所以在此就不再多說了。並且dict要求鍵必須是能被雜湊的不可變物件,因此普通的set無法作為dict的鍵,必須選擇被「凍結」的不可變集合類:frozenset。顧名思義,一旦初始化,集合內資料不可修改。

原文:

python字典的底層原理

無序,可變的容器資料結構,key value資料儲存 key可以為數值,字串,元組,但是唯一,value則支援多種資料型別 讀取速度快,時間複雜度o 1 o 1 o 1 python字典的底層實現是雜湊表,即帶有索引和儲存空間的表 如d 建立乙個空字典,初始化乙個長度為8 的c陣列arr 1.插入資...

3 4 字典的巢狀

1 字典的巢狀 1 stu info 3 xiaohei 4 2 巢狀字典的取值 1 stu info 3 xiaohei 4 5 print stu info xiaoming phone 3 巢狀字典的增刪改查 案例 1 d 4 house 北京 南京 上海 5 money 1000000 6 ...

1 8字典的運算

問題 怎樣在資料字典中執行一些計算操作 比如求最小值 最大值 排序等等 解決方案 考慮下面的骨片名稱和 對映字典 prices 為了對字典執行計算操作,通常需要使用zip 函式先將鍵和值反轉過來,比如,下面是查詢在最小和最大 值的 print min zip prices.values prices...