溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python 哈希表實現(xiàn)簡單python字典代碼實例

發(fā)布時間:2020-09-29 00:02:11 來源:腳本之家 閱讀:180 作者:DRQ丶 欄目:開發(fā)技術(shù)

這篇文章主要介紹了python 哈希表實現(xiàn)簡單python字典代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下

class Array(object):
  def __init__(self, size = 32, init = None):
    self._size = size
    self._items = [init] * size
  def __getitem__(self, index):
    return self._items[index]
  def __setitem__(self, index, value):
    self._items[index] = value
  def __len__(self):
    return self._size
  def clear(self, value = None):
    for i in range(self,_items):
      self._items[i] = value
  def __iter__(self):
    for item in self._items:
      yield item
class Slot(object):
  """
  定義一個哈希表數(shù)組的槽
  注意:一個槽有三種狀態(tài)
  1. 從未被使用過,HashMap.UNUSED。 此槽沒有被使用和沖突過,查找時只要找到UNUSED 就不用再繼續(xù)探查了
  2. 使用過但是remove了, 此時是HashMap.EMPTY,該談差點后面的元素仍可能是有key
  3. 槽正在使用Slot 節(jié)點
  """
  def __init__(self, key, value):
    self.key = key
    self.value = value
class HashTable(object):
  UNUSED = None # 表示slot 沒有被使用過
  EMPTY = Slot(None, None) # 使用過被刪除
  def __init__(self):
    self._table = Array(8, init = HashTable.UNUSED) # 初始化,數(shù)組的每個元素都是UNUSED
    self.length = 0
  @property # 內(nèi)置裝飾器,把方法變成屬性
  def _load_factor(self):
    return self.length/float(len(self._table))
  def __len__(self):
    return self.length
  def _hash(self, key):
    return abs(hash(key)) % len(self._table) # abs函數(shù)返回絕對值 hash 是內(nèi)置函數(shù) _hash 直接使用內(nèi)置的哈希函數(shù),對數(shù)組的長度取模
  def _find_key(self, key):
    index = self._hash(key) # 先用 _hash方法計算出槽的位置
    _len = len(self._table) # 現(xiàn)保存下來長度
    while self._table[index] is not HashTable.UNUSED:  # 如果這個槽不是沒有被使用過
      if self._table[index] is HashTable.EMPTY: # 如果這個槽是,曾經(jīng)有過值,不過被刪除了
        index = (index*5 +1 ) % _len    # cpython 使用的一種解決哈希沖突的方式
        continue
      elif self._table[index].key == key: # 正在使用, 如果key值相同
        return index
      else: # 這里就只剩最后一種可能, 正在使用,但是key沒有找到
        index = (index *5 +1) % _len
    return None
  def _slot_can_insert(self, index): # 判斷一個槽是否可以插入
    return (self._table[index] is HashTable.EMPTY or self._table[index] is HashTable.UNUSED)
  def _find_slot_for_insert(self,key):  # 尋找一個空槽,用來插入
    index = self._hash(key)
    _len = len(self._table)
    while not self._slot_can_insert(index):
      index = (index*5 + 1) % _len
    return index
  def __contains__(self, key):   # 實現(xiàn)一個in操作符
    index = self._find_key(key)
    return index is not None
  def add(self, key, value):
    if key in self:  # 上面實現(xiàn)的in操作符
      index = self._find_key(key)
      self._table[index].value = value
      return False  # 返回False 表示沒有執(zhí)行插入操作,執(zhí)行的是更新操作
    else:
      index = self._find_slot_for_insert(key)
      self._table[index] = Slot(key, value) # 這兩部可能會調(diào)用_slot_can_insert 函數(shù),不管是哪種情況,EMPTY 或 是 UNUSEZD,都將這個節(jié)點聲明為Slot類
      self.length += 1
      if self._load_factor >= 0.8:
        self._rehash()   # 當空間占用大于0.8 的時候,進行rehash 重新分配空間。
      return True
  def _rehash(self):
    old_table = self._table
    newsize = len(self._table) *2
    self._table = Array(newsize, HashTable.UNUSED)
    self.length = 0
    for slot in old_table:
      if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:  # 判斷這個slot 是有值的
        index = self._find_slot_for_insert(slot.key)  # 找到一個可以插入的槽
        self._table[index] = slot
        self.length += 1
  def get(self, key, default = None):
    index = self._find_key(key)
    if index is None:
      return default
    else:
      return self._table[index].value
  def remove(self,key):
    index = self._find_key(key)
    if index is None:
      raise KeyError()
    value = self._table[index].value
    self.length -= 1
    self._table[index] = HashTable.EMPTY
    return value
  def __iter__(self):   # 遍歷操作,python 字典默認遍歷的是key,這里實現(xiàn)的也是遍歷key
    for slot in self._table:
      if slot not in(HashTable.EMPTY, HashTable.UNUSED):
        yield slot.key
class DictADT(HashTable):

  def __setitem__(self, key, value):  # 設(shè)定給定鍵的值
    self.add(key, value)
  def __getitem__(self, key):   # 返回給定鍵的值
    if key not in self:
      raise KeyError()
    else:
      return self.get(key)
  def _iter_slot(self):
    for slot in self._table:
      if slot not in (HashTable.EMPTY, HashTable.UNUSED):
        yield slot
  def items(self):
    for slot in self._iter_slot():
      yield (slot.key, slot.value)
  def keys(self):
    for slot in self._iter_slot():
      yield slot.key
  def values(self):
    for slot in self._iter_slot():
      yield slot.value
def test_dict():
  import random
  d = DictADT()
  d['a'] = 1   # 這時候調(diào)用 __setitem__ 方法
  assert d['a'] == 1
  d.remove('a')
  l = list(range(30))
  random.suffle(l)  # 打亂l
  for i in l:
    d.add(i, i )
  for i in range(30):
    assert d.get(i) == i
  assert sorted (list(d.keys())) == sorted(l)

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI