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(Tornado)模拟登录小米抢手机
Nov 12 Python
python使用xmlrpc实例讲解
Dec 17 Python
Python入门之modf()方法的使用
May 15 Python
python直接访问私有属性的简单方法
Jul 25 Python
Python中对象迭代与反迭代的技巧总结
Sep 17 Python
Python解决抛小球问题 求小球下落经历的距离之和示例
Feb 01 Python
Python使用matplotlib绘制余弦的散点图示例
Mar 14 Python
利用PyCharm Profile分析异步爬虫效率详解
May 08 Python
Python学习笔记之迭代器和生成器用法实例详解
Aug 08 Python
python实现录屏功能(亲测好用)
Mar 02 Python
Python基础之常用库常用方法整理
Apr 30 Python
Python之Matplotlib绘制热力图和面积图
Apr 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
实现树状结构的两种方法
2006/10/09 PHP
PHP stristr() 函数(不区分大小写的字符串查找)
2010/06/03 PHP
PHP计划任务、定时执行任务的实现代码
2011/04/23 PHP
输入值/表单提交参数过滤有效防止sql注入的方法
2013/12/25 PHP
ThinkPHP框架实现的微信支付接口开发完整示例
2019/04/10 PHP
js禁止页面刷新禁止用F5键刷新禁止右键的示例代码
2013/09/23 Javascript
基于JQuery实现滚动到页面底端时自动加载更多信息
2014/01/31 Javascript
jquery 隐藏与显示tr标签示例代码
2014/06/06 Javascript
一个css与js结合的下拉菜单支持主流浏览器
2014/10/08 Javascript
第四篇Bootstrap网格系统偏移列和嵌套列
2016/06/21 Javascript
webpack进阶——缓存与独立打包的用法
2017/08/02 Javascript
JavaScript模块详解
2017/12/18 Javascript
浅谈Vue组件及组件的注册方法
2018/08/24 Javascript
Vuejs+vue-router打包+Nginx配置的实例
2018/09/20 Javascript
学习使用ExpressJS 4.0中的新Router的用法
2018/11/06 Javascript
详解如何用typescript开发koa2的二三事
2018/11/13 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
2018/11/27 jQuery
[01:02:25]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS VG
2014/05/25 DOTA
Python遍历目录的4种方法实例介绍
2015/04/13 Python
CentOS 6.5中安装Python 3.6.2的方法步骤
2017/12/03 Python
python如何为创建大量实例节省内存
2018/03/20 Python
python线程池threadpool实现篇
2018/04/27 Python
Python实现的爬虫刷回复功能示例
2018/06/07 Python
numpy 计算两个数组重复程度的方法
2018/11/07 Python
python读取多层嵌套文件夹中的文件实例
2020/02/27 Python
python能自学吗
2020/06/18 Python
英国最大的LED专业零售商:Led Hut
2018/03/16 全球购物
Linden Leaves官网:新西兰纯净护肤品
2020/12/20 全球购物
实习报告评语
2014/04/26 职场文书
艾滋病宣传标语
2014/06/25 职场文书
教师国庆节演讲稿范文2014
2014/09/21 职场文书
学校运动会广播稿
2014/10/11 职场文书
法制教育主题班会
2015/08/13 职场文书
导游词之镜泊湖
2019/12/09 职场文书
mysql事务对效率的影响分析总结
2021/10/24 MySQL
Nginx性能优化之Gzip压缩设置详解(最大程度提高页面打开速度)
2022/02/12 Servers