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基础教程之基本内置数据类型介绍
Feb 20 Python
Python getopt模块处理命令行选项实例
May 13 Python
Python安装Imaging报错:The _imaging C module is not installed问题解决方法
Aug 22 Python
Python中变量交换的例子
Aug 25 Python
深入解析Python中的线程同步方法
Jun 14 Python
python中requests小技巧
May 10 Python
Python实现桶排序与快速排序算法结合应用示例
Nov 22 Python
Python实现的堆排序算法示例
Apr 29 Python
使用python3批量下载rbsp数据的示例代码
Dec 20 Python
细数nn.BCELoss与nn.CrossEntropyLoss的区别
Feb 29 Python
使用 Python 读取电子表格中的数据实例详解
Apr 17 Python
TensorFlow保存TensorBoard图像操作
Jun 23 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遍历目录并返回统计目录大小
2014/06/09 PHP
php查看网页源代码的方法
2015/03/13 PHP
php结合安卓客户端实现查询交互实例
2015/05/05 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
2015/11/09 PHP
PHP使用内置函数生成图片的方法详解
2016/05/09 PHP
thinkphp5 URL和路由的功能详解与实例
2017/12/26 PHP
YII框架实现自定义第三方扩展操作示例
2019/04/26 PHP
通过JavaScript使Div居中并随网页大小改变而改变
2013/06/24 Javascript
node.js中的buffer.toJSON方法使用说明
2014/12/14 Javascript
分享33个jQuery与CSS3实现的绚丽鼠标悬停效果
2014/12/15 Javascript
jQuery对指定元素中指定字符串进行替换的方法
2015/03/17 Javascript
javascript多物体运动实现方法分析
2016/01/08 Javascript
15位和18位身份证JS校验的简单实例
2016/07/18 Javascript
Angular的自定义指令以及实例
2016/12/26 Javascript
JS获得多个同name 的input输入框的值的实现方法
2017/01/09 Javascript
NodeJs实现定时任务的示例代码
2017/12/05 NodeJs
jQuery仿移动端支付宝键盘的实现代码
2018/08/15 jQuery
vue中当图片地址无效的时候,显示默认图片的方法
2018/09/18 Javascript
javascript 模块依赖管理的本质深入详解
2020/04/30 Javascript
python 全文检索引擎详解
2017/04/25 Python
python实现感知器
2017/12/19 Python
python微信跳一跳系列之棋子定位颜色识别
2018/02/26 Python
深入理解Python 关于supper 的 用法和原理
2018/02/28 Python
python爬虫自动创建文件夹的功能
2018/08/01 Python
Python中pymysql 模块的使用详解
2019/08/12 Python
python 图像的离散傅立叶变换实例
2020/01/02 Python
如何快速理解python的垃圾回收机制
2020/09/01 Python
Python浮点型(float)运算结果不正确的解决方案
2020/09/22 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
美国流行背包品牌:JanSport(杰斯伯)
2018/03/02 全球购物
伯克斯奥特莱斯:Burkes Outlet
2019/03/30 全球购物
英语师范专业毕业生自荐信
2013/09/21 职场文书
小区推广策划方案
2014/06/06 职场文书
经营理念口号
2014/06/21 职场文书
2019年作为一名实习生的述职报告
2019/09/29 职场文书
解决persistence.xml配置文件修改存放路径的问题
2022/02/24 Java/Android