python 下的數據結構與算法---8:哈希一下【dict與set的實現】

少年,不知道你好記不記得第三篇文章講python內建數據結構的方法及其時間複雜度時裏面關於dict與set的時間複雜度[爲什麼訪問元素爲O(1)]原理我說後面講嗎?其實就是這篇文章講啦。html

目錄:python

  一:Hash的定義算法

  二:dict與set的實現原理數據結構

  三:經常使用構造hash函數的方法ide

  四:hash碰撞及其解決方法函數

  五:dict的實現spa

 

一:Hash的定義翻譯

  Hash,通常翻譯作「散列」,就是把任意長度的輸入,經過散列算法,變換成固定長度的輸出,該輸出就是散列值。【不一樣的輸入可能會散列成相同的輸出,因此不可能從散列值來惟一的肯定輸入值】3d

 

二:dict與set的實現原理指針

  dict與set實現原理是同樣的,都是將實際的值放到list中。惟一不一樣的在於hash函數操做的對象,對於dict,hash函數操做的是其key,而對於set是直接操做的它的元素,假設操做內容爲x,其做爲因變量,放入hash函數,經過運算後取list的餘數,轉化爲一個list的下標,此下標位置對於set而言用來放其自己,而對於dict則是建立了兩個list,一個list該下表放此key,另外一個list中該下標方對應的value。

  其中,咱們把實現set的方式叫作Hash Set,實現dict的方式叫作Hash Map/Table(注:map指的就是經過key來尋找value的過程)

 

三:經常使用構造hash函數的方法

  1:摺疊法

    將每一個元素分爲相等的幾部分後相加後再除以list長度,e.g:若是項目是436-555-4601, 以2爲分組,分紅了 (43, 65, 55, 46, 01). 所有加起來:43 + 65 + 55 + 46 + 01 = 210. 假設list有11個元素, 則210%11 =1, 因此將436-555-4601放到list下標爲1的地方。

  

  2:取中法:

    如元素44平方後得1936取中93再取list的餘

    

  注:對於string其所對應的數字可用其ASCII碼來代替(還可與位數結合,見圖5.7)ord('a')可返回'a'的ASCII碼

    

  注:此地就是爲何dict與set訪問元素時間複雜度爲O(1)的緣由了,經過對元素的hash函數運算後可以直接知道其下標,因此爲O(1)

 

四:hash碰撞及其解決方法

  定義裏面講到過不一樣的輸入可能會散列成相同的輸出,因此就可能出現名爲「哈希碰撞」的狀況,也就是說兩個不一樣的元素算出來的下標值同樣,此時就有兩種解決方法:

  1:向後探測

      架設一個元素算出來下標爲5,另外一個元素算出來下標也爲5,從開頭開始探測第0第1位是否爲空,當看到爲空的就放入,不過這樣相鄰探測的很差之處在於容易發生彙集,因此最好是跳躍着進行探測,定義一個skip的值,好比3,用方程rehash(pos) = (pos + skip)%sizeoftable,即便查看0,3,6這樣跳躍着來

  2:鏈式存儲

    原理圖以下,其實就是將發生有衝突的元素放到同一位置,而後經過「指針「來串聯起來

    

 

五:HashTable

  下面將寫一個hashTable,而實際中的dict就是由hashTable擴展而來的

 

 1 class HashTable:
 2     def __init__(self):
 3         self.size = 11
 4         self.slots = [None] * self.size
 5         self.data = [None] * self.size
 6 
 7     def hash_function(self, key, size):
 8         return key % size
 9     def rehash(self, old_hash, size):
10         return (old_hash + 1) % size
11     def __getitem__(self, key):
12         return self.get(key)
13     def __setitem__(self, key, data):
14         self.put(key, data)
15 
16     def put(self, key, data):
17         hash_value = self.hash_function(key,len(self.slots))
18         if self.slots[hash_value] == None:
19             self.slots[hash_value] = key
20             self.data[hash_value] = data
21         elif self.slots[hash_value] == key:
22             self.data[hash_value] = data        # replace
23         else:
24             next_slot = self.rehash(hash_value, len(self.slots))
25             while self.slots[next_slot] != None and self.slots[next_slot] != key:
26                 next_slot = self.rehash(next_slot, len(self.slots))
27                 if self.slots[next_slot] == None:
28                     self.slots[next_slot] = key
29                     self.data[next_slot] = data
30                 else:
31                     self.data[next_slot] = data     #replace
32 
33     def get(self, key):
34         start_slot = self.hash_function(key, len(self.slots))
35         data = None
36         stop = False
37         found = False
38         position = start_slot
39         while self.slots[position] != None and not found and not stop:
40             if self.slots[position] == key:
41                 found = True
42                 data = self.data[position]
43             else:
44                 position=self.rehash(position, len(self.slots))
45                 if position == start_slot:
46                     stop = True
47         return data
HashTable
相關文章
相關標籤/搜索