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 14 Python
Python中的ctime()方法使用教程
May 22 Python
在Python的Flask框架中验证注册用户的Email的方法
Sep 02 Python
Python中的条件判断语句基础学习教程
Feb 07 Python
python之PyMongo使用总结
May 26 Python
python导入csv文件出现SyntaxError问题分析
Dec 15 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 Python
在Python中居然可以定义两个同名通参数的函数
Jan 31 Python
Python datetime和unix时间戳之间相互转换的讲解
Apr 01 Python
Python Pandas 箱线图的实现
Jul 23 Python
基于spring boot 日志(logback)报错的解决方式
Feb 20 Python
Python中Selenium模块的使用详解
Oct 09 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随机字符串生成代码(包括大小写字母)
2013/06/24 PHP
PHP XML和数组互相转换详解
2016/10/26 PHP
服务器安全设置的几个注册表设置
2007/07/28 Javascript
JS 无法通过W3C验证的处理方法
2010/03/09 Javascript
jQuery 下拉列表 二级联动插件分享
2012/03/29 Javascript
javascript判断是手机还是电脑访问网页的简单实例分享
2014/06/03 Javascript
jQuery中hasClass()方法用法实例
2015/01/06 Javascript
javascript面向对象快速入门实例
2015/01/13 Javascript
Bootstrap时间选择器datetimepicker和daterangepicker使用实例解析
2016/09/17 Javascript
关于RequireJS的简单介绍即使用方法
2016/10/20 Javascript
js实现百度地图定位于地址逆解析,显示自己当前的地理位置
2016/12/08 Javascript
vue仿淘宝订单状态的tab切换效果
2020/06/23 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
node简单实现一个更改头像功能的示例
2017/12/29 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
2020/07/18 Javascript
VUE : vue-cli中去掉路由中的井号#操作
2020/09/04 Javascript
vue3弹出层V3Popup实例详解
2021/01/04 Vue.js
python脚本实现查找webshell的方法
2014/07/31 Python
Python中的MongoDB基本操作:连接、查询实例
2015/02/13 Python
Python简单删除目录下文件以及文件夹的方法
2015/05/27 Python
python生成器generator用法实例分析
2015/06/04 Python
python 获取url中的参数列表实例
2018/12/18 Python
python flask安装和命令详解
2019/04/02 Python
python列表每个元素同增同减和列表元素去空格的实例
2019/07/20 Python
Python 操作mysql数据库查询之fetchone(), fetchmany(), fetchall()用法示例
2019/10/17 Python
opencv python在视屏上截图功能的实现
2020/03/05 Python
Ubuntu权限不足无法创建文件夹解决方案
2020/11/14 Python
深入探究HTML5的History API
2015/07/09 HTML / CSS
党员学习十八大感想
2014/01/17 职场文书
餐厅执行经理岗位职责范本
2014/02/26 职场文书
护理人员的自我评价分享
2014/03/15 职场文书
2014年综合治理工作总结
2014/11/20 职场文书
2016学校先进党组织事迹材料
2016/02/29 职场文书
vite+vue3.0+ts+element-plus快速搭建项目的实现
2021/06/24 Vue.js
Java数组详细介绍及相关工具类
2022/04/14 Java/Android
MySQL详细讲解变量variables的用法
2022/06/21 MySQL