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下尝试多线程编程
Apr 28 Python
Python实现简单多线程任务队列
Feb 27 Python
Python smtplib实现发送邮件功能
May 22 Python
python 实现将字典dict、列表list中的中文正常显示方法
Jul 06 Python
Python拼接微信好友头像大图的实现方法
Aug 01 Python
Python基于mysql实现学生管理系统
Feb 21 Python
Python面向对象之继承和多态用法分析
Jun 08 Python
django中SMTP发送邮件配置详解
Jul 19 Python
TensorBoard 计算图的查看方式
Feb 15 Python
解决 jupyter notebook 回车换两行问题
Apr 15 Python
python自动化办公操作PPT的实现
Feb 05 Python
详解python中[-1]、[:-1]、[::-1]、[n::-1]使用方法
Apr 25 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
php 图片上添加透明度渐变的效果
2009/06/29 PHP
php读取der格式证书乱码解决方法
2015/06/22 PHP
PHP中spl_autoload_register()函数用法实例详解
2016/07/18 PHP
php实现的统计字数函数定义与使用示例
2017/07/26 PHP
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
Javascript 表单之间的数据传递代码
2008/12/04 Javascript
jquery 简短右键菜单 多浏览器兼容
2010/01/01 Javascript
JavaScript 滚轮事件使用说明
2010/03/07 Javascript
javascript 通用简单的table选项卡实现
2010/05/07 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
javascript中setTimeout的问题解决方法
2014/05/08 Javascript
node+express+jade制作简单网站指南
2014/11/26 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
2015/10/23 Javascript
详解JavaScript逻辑And运算符
2015/12/04 Javascript
RequireJS多页面应用实例分析
2016/06/29 Javascript
老生常谈 js中this的指向
2016/06/30 Javascript
Angular.js实现注册系统的实例详解
2016/12/18 Javascript
JS实现点击循环切换显示内容的方法
2017/10/19 Javascript
javascript中undefined的本质解析
2019/07/31 Javascript
Python tkinter事件高级用法实例
2018/01/31 Python
python方法生成txt标签文件的实例代码
2018/05/10 Python
Python清空文件并替换内容的实例
2018/10/22 Python
Python MOCK SERVER moco模拟接口测试过程解析
2020/04/13 Python
Python urllib3软件包的使用说明
2020/11/18 Python
一款基于css3和jquery实现的动画显示弹出层按钮教程
2015/01/04 HTML / CSS
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
德国体育用品网上商店:SC24.com
2016/08/01 全球购物
英国设计师泳装、沙滩装和比基尼在线精品店:Beach Cafe
2019/08/28 全球购物
NICKIS.com荷兰:设计师儿童时装
2020/01/08 全球购物
数据库方面面试题
2012/04/22 面试题
Linux管理员面试经常问道的相关命令
2013/04/29 面试题
大学生专科学习生活的自我评价
2013/12/07 职场文书
领导干部群众路线个人对照检查材料思想汇报
2014/09/30 职场文书
大客户经理岗位职责
2015/04/09 职场文书
2015年新教师工作总结
2015/04/28 职场文书