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算法学习之桶排序算法实例(分块排序)
Dec 18 Python
Python2.7基于笛卡尔积算法实现N个数组的排列组合运算示例
Nov 23 Python
详解Pytorch 使用Pytorch拟合多项式(多项式回归)
May 24 Python
Python 中的lambda函数介绍
Oct 10 Python
python实现银联支付和支付宝支付接入
May 07 Python
django如何通过类视图使用装饰器
Jul 24 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
Jul 26 Python
django多文件上传,form提交,多对多外键保存的实例
Aug 06 Python
python文件处理fileinput使用方法详解
Jan 02 Python
keras的load_model实现加载含有参数的自定义模型
Jun 22 Python
python爬虫工具例举说明
Nov 30 Python
Python爬虫基础初探selenium
May 31 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上传图片重命名的6种解决方法的详细介绍
2013/04/28 PHP
PHP常用设计模式之委托设计模式
2016/02/13 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
thinkPHP+ajax实现统计页面pv浏览量的方法
2017/03/15 PHP
PHP中$GLOBALS['HTTP_RAW_POST_DATA']和$_POST的区别分析
2017/07/03 PHP
php处理抢购类功能的高并发请求
2018/02/08 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
js window.event对象详尽解析
2009/02/17 Javascript
javascript 面向对象全新理练之原型继承
2009/12/03 Javascript
jquery(hide方法)隐藏指定元素实例
2013/11/11 Javascript
jQuery中fadeOut()方法用法实例
2014/12/24 Javascript
js实现精确到秒的倒计时效果
2016/05/29 Javascript
D3.js实现文本的换行详解
2016/10/14 Javascript
简单理解vue中实例属性vm.$els
2016/12/01 Javascript
jQuery插件HighCharts实现的2D条状图效果示例【附demo源码下载】
2017/03/15 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
使用Vue开发一个实时性时间转换指令
2018/01/17 Javascript
js提取中文拼音首字母的封装工具类
2018/03/12 Javascript
Vue 通过自定义指令回顾v-内置指令(小结)
2018/09/03 Javascript
基于vue的验证码组件的示例代码
2019/01/22 Javascript
详解Vue前端对axios的封装和使用
2019/04/01 Javascript
微信小程序 多行文本显示...+显示更多按钮和收起更多按钮功能
2019/09/26 Javascript
关于JavaScript中异步/等待的用法与理解
2020/11/18 Javascript
python判断端口是否打开的实现代码
2013/02/10 Python
python入门基础之用户输入与模块初认识
2016/11/14 Python
Python-jenkins模块获取jobs的执行状态操作
2020/05/12 Python
Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)
2020/12/14 Python
HTML5在a标签内放置块级元素示例代码
2013/08/23 HTML / CSS
eDreams巴西:廉价机票,酒店优惠和度假套餐
2017/04/14 全球购物
女士和男士时尚鞋在线购物:Shoespie
2019/02/28 全球购物
英国手机壳购买网站:Case Hut
2019/04/11 全球购物
清华大学自主招生自荐信
2014/01/29 职场文书
小学生评语集锦
2014/04/18 职场文书
2016年小学教师政治学习心得体会
2016/01/23 职场文书
Redis IP地址的绑定的实现
2021/05/08 Redis
Python带你从浅入深探究Tuple(基础篇)
2021/05/15 Python