概念
Python中的Dict是一種使用最為普遍的數據結構,特別是數據之間具有關聯關系時。上一博文提到了hash function和hash table的概念,現在來用代碼實現HashTable。
我們通過兩個list來分別存儲key和value,這就要求兩個list的大小一致,在對應的index上分別存儲key和value。實現HashTable最重要的兩個方法是set和get方法,如果通過Class來實現,則需要實現特殊方法__setitem__和__getitem__。這樣就可以通過索引來取值。
構造方法
class HashTable:
def __init__(self):
self.size = 11
self.slots = [None] * self.size
self.data = [None] * self.size
確定一個HashTable的長度,並且存儲key(slots)和value(data)的list也保持大小一致,且都初始化為None。
hash_function和rehash方法
def hash_function(self, key, size):
return key % size
def rehash(self, old_hash, size):
return (old_hash + 1) % size
通過hash_function方法確定key在hash table中的索引位置,通過rehash消除collision(不同的key經過hash function計算得到相同的index)。
set方法
def set(self, key, value):
hash_value = self.hash_function(key, len(self.slots))
if self.slots[hash_value] is None:
self.slots[hash_value] = key
self.data[hash_value] = value
else:
if self.slots[hash_value] == key:
self.data[hash_value] = value
else:
next_slot = self.rehash(hash_value, len(self.slots))
while self.slots[next_slot] is not None and self.slots[
next_slot] != key:
next_slot = self.rehash(next_slot, len(self.slots))
if self.slots[next_slot] is None:
self.slots[next_slot] = key
self.data[next_slot] = value
else:
self.data[next_slot] = value
set方法的邏輯是:先通過hash function計算key的hash值,然后在保存key的slots(list)中查找對應位置的值是否存在,若不存在,則在該位置保存key,在data(list)中保存key對應的value。
若在slots對應的位置處恰好為key,則update其value。反之,若在slots對應的位置處不為key,則說明發生了collision(數據沖突),那么我們通過rehash方法繼續hash,找到一個空余的位置,將該鍵值對(key和value)放入該位置或僅更新其value。
get方法
def get(self, key):
start_slot = self.hash_function(key, len(self.slots))
position = start_slot
data = None
while self.slots[position] is not None:
if self.slots[position] == key:
data = self.data[position]
break
else:
position = self.rehash(position, len(self.slots))
if position == start_slot:
break
return data
get方法較為簡單,也是先獲取hash值,然后查找slots在該hash值處所對應的值是否存在,若存在,則判斷保存的key是否和要查找的key相等,若相等則返回該值,若不相等則說明發生collision,則使用rehash繼續查找。記住,rehash方法必須有一個判斷機制,用以判斷是否遍歷完整個hash table(循環一圈,回到初次hash值)。
__setitem__和__getitem__方法
def __getitem__(self, key):
return self.get(key)
def __setitem__(self, key, value):
self.put(key, value)
這兩個方法主要是類似Pyhton字典中的set和get語法,如dic[key] = value。
總結:上述實踐僅僅是一個簡單的demo。實際對應hash table的大小,hash function的實現有各個各樣的方法,在這里僅起到一個拋磚引玉的作用。