【 python 學習筆記,python學習筆記
Python內建的字典就是用 hash table實現的。這裡我們只是通過實現自己的hash table來加深對hash table 和hash functions的理解。
【 概念1: Mapping (映射)】
字典通過鍵(Key)來索引。一個key對應一個儲存的value。任意不可變的資料類型均可作為key。
【 概念2:Hash Table (雜湊表)】
Hash Table根據key直接存取在記憶體儲存位置的資料結構,因而加快了尋找速度 (O(1))。
是一個size為11的空的Hash Table, 每一個元素初始化為None:
【 概念3: Hash function (散列函數) 】
key對應的value存放在f(key)的儲存位置上,這個對應關係f就叫做Hash Function:
構造Hash Function的方法有很多:
例如 (1) Remainder Method (除留餘數法):
假設我們有一個空的Hash Table, 它的size (表長)為11, 現在我們要在Hash Table 中存放一系列整數key: 54, 26, 93, 17, 77, 31;則 remainder hash function 為 h(key)=key%11。
結果如下:
現在我們的hash table變成:
【概念4: load factor (載荷因子) 】λ=number_of_keys/table_size. 在上述例子中,我們存放了6個items, hash table的長度為11, 則其對應的載荷因子為6/11。
當我們想要尋找一個key的時候,我們只需要利用hash function算出相應的儲存位置(slot name) ,查看該位置是否儲存了key。這一搜尋操作時間複雜性為O(1)。
【概念5: collision or clash (衝突) 】:兩個items可能對應同一個hash function地址,這種情況稱為衝突。 例如當我們採用remainder hash function時, 44%11 和77%11都等於0。
這種情況下需要選另外的hash function, 或對衝突結果進行處理。
我們先來介紹其他幾種hash function。我們希望能構建一個hash function,使得發生衝突的數量最小化,便於計算,並且在hash table中均勻分布:
(2)Folding Method (摺疊法):
將關鍵字(key)分割成位元相同的幾部分(最後一部分位元可能不同),然後將這幾部分求和,最後再做除留餘數法。
例如:我們的key是一個電話號碼4365554601,兩個數字為一組(43,65,55,46,01),將這些部分求和43+65+55+46+01=210,最後求餘210%11=1。 因此這個電話號碼在
hash table 中儲存在slot 1。
(3)Mid-square Method (平方取中法):
將關鍵字取平方後,取其中間的幾位元求餘作為雜湊地址。
例如: 我們的key是44, 首先取平方44^2=1936, 然後取中間的兩位元字93,再取餘數93%11=5即為其雜湊地址。
對於非整數的key,例如string(字串),我們可以利用其ordinal values來計算:
例如 字串'cat', ord('c')=99, ord('a')=97, ord('t')=116, 所以對應的雜湊地址可以是(99+97+116)%11 =4
接下來,我們討論【衝突處理】的方法:
(1) open addressing (開放定址法): 當發生衝突時,我們在hash table中尋找下一個空的位置來存放發生衝突的key。這裡介紹兩種尋找的方式:
(i) Linear Probing (線性探測): 相當於逐個探測hash table,直到尋找到一個空的slot,把key存放在該位置。例如,發生衝突的hash value是h, 後面尋找的順序為h+1, h+2, h+3...
為了防止聚集(clustering),可採用 skip slots的方法。
(ii) Quadratic Probing (平方探測): 即,發生衝突的hash value是h,則下一個尋找的位置為h+1, 再後面的為h+4,h+9,h+16...
(2)chaining (鏈表法):將hash value相同的所有元素儲存在一個鏈表中。但發生同一個位置連結的元素越多,搜尋難度越大。鏈表的如下:
最後,我們來實現自己的Hash Table, 另其包含以下幾種methods:
HashTable(size): 建立一個新的,空的映射。它返回一個空的映射集合,初始化表長為size
put(key,val):向表中添加一對新的key-value。如果表中已經存在這個key,則更新這個key對應的value。
get(key): 給定一個key,返回其對應的value。如果表中不存在這個key則返回None
del : 通過使用 del map[key] 刪除對應的key-value。
len(): 返回表中存放的key-value對的數量
in: 使用key in map判斷key是否在map中,在則返回True,不在則返回False