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分割和拼接字符串
Nov 01 Python
零基础写python爬虫之HTTP异常处理
Nov 05 Python
探究Python多进程编程下线程之间变量的共享问题
May 05 Python
基于python的Tkinter实现一个简易计算器
Dec 31 Python
python自动裁剪图像代码分享
Nov 25 Python
python将文本分每两行一组并保存到文件
Mar 19 Python
对python 矩阵转置transpose的实例讲解
Apr 17 Python
django将网络中的图片,保存成model中的ImageField的实例
Aug 07 Python
Python lxml库的简单介绍及基本使用讲解
Dec 22 Python
Python调用系统命令os.system()和os.popen()的实现
Dec 31 Python
Python中的pprint模块
Nov 27 Python
Python采集壁纸并实现炫轮播
Apr 30 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强制下载类型的实现代码
2011/04/21 PHP
基于PHP读取csv文件内容的详解
2013/06/18 PHP
设置php页面编码的两种方法示例介绍
2014/03/03 PHP
php中cookie的使用方法
2014/03/29 PHP
php计算数组相同值出现次数的代码(array_count_values)
2015/01/20 PHP
微信公众平台开发实现2048游戏的方法
2015/04/15 PHP
php+html5实现无刷新图片上传教程
2016/01/22 PHP
thinkPHP引入类的方法详解
2016/12/08 PHP
CakePHP框架Model函数定义方法示例
2017/08/04 PHP
JQueryEasyUI Layout布局框架的使用
2013/04/08 Javascript
你必须知道的JavaScript 中字符串连接的性能的一些问题
2013/05/07 Javascript
jquery属性选择器not has怎么写 行悬停高亮显示
2013/11/13 Javascript
jquery操作checkbox实现全选和取消全选
2014/05/02 Javascript
JavaScript基于setTimeout实现计数的方法
2015/05/08 Javascript
jquery判断输入密码两次是否相等
2020/04/22 Javascript
Jquery技巧(必须掌握)
2016/03/16 Javascript
vue项目中做编辑功能传递数据时遇到问题的解决方法
2016/12/19 Javascript
Vue-Cli中自定义过滤器的实现代码
2017/08/12 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
2017/12/26 Javascript
在 Vue 中使用 JSX 及使用它的原因浅析
2020/02/10 Javascript
vue动态设置页面title的方法实例
2020/08/23 Javascript
Antd的table组件表格的序号自增操作
2020/10/27 Javascript
Vue+Spring Boot简单用户登录(附Demo)
2020/11/12 Javascript
pyqt4教程之实现windows窗口小示例分享
2014/03/07 Python
Python编程实现输入某年某月某日计算出这一天是该年第几天的方法
2017/04/18 Python
python用post访问restful服务接口的方法
2018/12/07 Python
python 读取文件并把矩阵转成numpy的两种方法
2019/02/12 Python
PyQt5 加载图片和文本文件的实例
2019/06/14 Python
Python实现投影法分割图像示例(一)
2020/01/17 Python
Python任务调度模块APScheduler使用
2020/04/15 Python
css3实现3D文本悬停改变效果的示例代码
2019/01/16 HTML / CSS
四年的大学生生活自我评价
2013/12/09 职场文书
网吧消防安全责任书
2014/07/29 职场文书
刑事辩护授权委托书
2014/09/13 职场文书
婚礼答谢词
2015/01/04 职场文书
Redis数据同步之redis shake的实现方法
2022/04/21 Redis