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 相关文章推荐
wxpython 最小化到托盘与欢迎图片的实现方法
Jun 09 Python
Windows下用py2exe将Python程序打包成exe程序的教程
Apr 08 Python
Python实现mysql数据库更新表数据接口的功能
Nov 19 Python
numpy.std() 计算矩阵标准差的方法
Jul 11 Python
Django ModelForm组件使用方法详解
Jul 23 Python
详解django实现自定义manage命令的扩展
Aug 13 Python
浅谈SciPy中的optimize.minimize实现受限优化问题
Feb 29 Python
django rest framework serializer返回时间自动格式化方法
Mar 31 Python
查看已安装tensorflow版本的方法示例
Apr 19 Python
简单了解python关键字global nonlocal区别
Sep 21 Python
怎么解决pycharm license Acti的方法
Oct 28 Python
python代码实现备忘录案例讲解
Jul 26 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
地摊中国 - 珍藏老照片
2020/08/18 杂记
php 分页函数multi() discuz
2009/06/21 PHP
鸡肋的PHP单例模式应用详解
2013/06/03 PHP
php循环table实现一行两列显示的方法
2015/06/04 PHP
PHP正则获取页面所有图片地址
2016/03/23 PHP
PHP获取表单数据与HTML嵌入PHP脚本的实现
2017/02/09 PHP
详解CSS样式中的 !important * _ 符号
2021/03/09 HTML / CSS
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
NodeJS Express框架中处理404页面一个方式
2014/05/28 NodeJs
JS判断元素是否在数组内的实现代码
2016/03/30 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
js实现简单的计算器功能
2017/01/16 Javascript
在vue项目中,使用axios跨域处理
2018/03/07 Javascript
angular 数据绑定之[]和{{}}的区别
2018/09/25 Javascript
详解angularjs跨页面传参遇到的一些问题
2018/11/01 Javascript
如何用RxJS实现Redux Form
2018/12/29 Javascript
layui复选框的全选与取消实现方法
2019/09/02 Javascript
javascript简单实现深浅拷贝过程详解
2019/10/08 Javascript
Vue中点击active并第一个默认选中功能的实现
2020/02/24 Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
2020/04/17 Javascript
Node.js设置定时任务之node-schedule模块的使用详解
2020/04/28 Javascript
js canvas实现五子棋小游戏
2021/01/22 Javascript
[01:00:52]2018DOTA2亚洲邀请赛 4.4 淘汰赛 EG vs LGD 第一场
2018/04/05 DOTA
[39:18]完美世界DOTA2联赛PWL S3 Forest vs LBZS 第二场 12.17
2020/12/19 DOTA
gearman的安装启动及python API使用实例
2014/07/08 Python
基于Python实现通过微信搜索功能查看谁把你删除了
2016/01/27 Python
Python3 socket同步通信简单示例
2017/06/07 Python
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
Python3.6日志Logging模块简单用法示例
2018/06/14 Python
快速解决vue.js 模板和jinja 模板冲突的问题
2019/07/26 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
学生如何注册Pycharm专业版以及pycharm的安装
2020/09/24 Python
五个2015 年最佳HTML5 框架
2015/11/11 HTML / CSS
html5自定义video标签的海报与播放按钮功能
2019/12/04 HTML / CSS
应届优秀本科大学毕业生自我鉴定
2014/01/21 职场文书
Opencv中cv2.floodFill算法的使用
2021/06/18 Python