python 哈希表实现简单python字典代码实例


Posted in Python onSeptember 27, 2019

这篇文章主要介绍了python 哈希表实现简单python字典代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

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):
  """
  定义一个哈希表数组的槽
  注意:一个槽有三种状态
  1. 从未被使用过,HashMap.UNUSED。 此槽没有被使用和冲突过,查找时只要找到UNUSED 就不用再继续探查了
  2. 使用过但是remove了, 此时是HashMap.EMPTY,该谈差点后面的元素仍可能是有key
  3. 槽正在使用Slot 节点
  """
  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) # 初始化,数组的每个元素都是UNUSED
    self.length = 0
  @property # 内置装饰器,把方法变成属性
  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函数返回绝对值 hash 是内置函数 _hash 直接使用内置的哈希函数,对数组的长度取模
  def _find_key(self, key):
    index = self._hash(key) # 先用 _hash方法计算出槽的位置
    _len = len(self._table) # 现保存下来长度
    while self._table[index] is not HashTable.UNUSED:  # 如果这个槽不是没有被使用过
      if self._table[index] is HashTable.EMPTY: # 如果这个槽是,曾经有过值,不过被删除了
        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):   # 实现一个in操作符
    index = self._find_key(key)
    return index is not None
  def add(self, key, value):
    if key in self:  # 上面实现的in操作符
      index = self._find_key(key)
      self._table[index].value = value
      return False  # 返回False 表示没有执行插入操作,执行的是更新操作
    else:
      index = self._find_slot_for_insert(key)
      self._table[index] = Slot(key, value) # 这两部可能会调用_slot_can_insert 函数,不管是哪种情况,EMPTY 或 是 UNUSEZD,都将这个节点声明为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,这里实现的也是遍历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):  # 设定给定键的值
    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   # 这时候调用 __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)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python高级应用实例对比:高效计算大文件中的最长行的长度
Jun 08 Python
在Python中操作字典之update()方法的使用
May 22 Python
Python代码实现KNN算法
Dec 20 Python
Python Json序列化与反序列化的示例
Jan 31 Python
Python 使用folium绘制leaflet地图的实现方法
Jul 05 Python
Django 多表关联 存储 使用方法详解 ManyToManyField save
Aug 09 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
Aug 15 Python
Python操作SQLite/MySQL/LMDB数据库的方法
Nov 07 Python
Python日志syslog使用原理详解
Feb 18 Python
python zip,lambda,map函数代码实例
Apr 04 Python
pandas分组聚合详解
Apr 10 Python
Python numpy矩阵处理运算工具用法汇总
Jul 13 Python
python实现发送form-data数据的方法详解
Sep 27 #Python
PyCharm更改字体和界面样式的方法步骤
Sep 27 #Python
Pycharm 字体大小调整设置的方法实现
Sep 27 #Python
python3 写一个WAV音频文件播放器的代码
Sep 27 #Python
简单瞅瞅Python vars()内置函数的实现
Sep 27 #Python
Python 获取项目根路径的代码
Sep 27 #Python
Python Pandas对缺失值的处理方法
Sep 27 #Python
You might like
基于mysql的论坛(2)
2006/10/09 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
2014/12/16 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
2016/10/10 PHP
解决PHP 7编译安装错误:cannot stat ‘phar.phar’: No such file or directory
2017/02/25 PHP
textarea的value是html文件源代码,存成html文件的代码
2007/04/20 Javascript
纯js实现背景图片切换效果代码
2010/11/14 Javascript
js阻止事件追加的具体实现
2014/10/15 Javascript
easyui Draggable组件实现拖动效果
2015/08/19 Javascript
基于JavaScript实现快速转换文本语言(繁体中文和简体中文)
2016/03/07 Javascript
jQuery Ajax传值到Servlet出现乱码问题的解决方法
2016/10/09 Javascript
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
分析javascript原型及原型链
2018/03/18 Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
2018/09/03 Javascript
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
微信小程序swiper使用网络图片不显示问题解决
2019/12/13 Javascript
[14:24]Optic Gaming vs PSG LGD BO3
2018/06/07 DOTA
python利用Guetzli批量压缩图片
2017/03/23 Python
python urllib爬取百度云连接的实例代码
2017/06/19 Python
python实现屏保计时器的示例代码
2018/08/08 Python
对python修改xml文件的节点值方法详解
2018/12/24 Python
Python实现的IP端口扫描工具类示例
2019/02/15 Python
使用Python将Mysql的查询数据导出到文件的方法
2019/02/25 Python
Python  Django 母版和继承解析
2019/08/09 Python
在Matplotlib图中插入LaTex公式实例
2020/04/17 Python
Python3爬虫中Ajax的用法
2020/07/10 Python
Python如何定义有默认参数的函数
2020/08/10 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
2020/12/07 Python
HTML5之tabindex属性全面解析
2016/07/07 HTML / CSS
JVM是一个编译程序还是解释程序
2012/09/11 面试题
幼儿园小班家长寄语
2014/04/02 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书
细节决定成败演讲稿
2014/05/12 职场文书
基层党员对照检查材料
2014/08/25 职场文书
Redis6.0搭建集群Redis-cluster的方法
2021/05/08 Redis
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
2021/05/30 Javascript
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python