Python 实现集合Set的示例


Posted in Python onDecember 21, 2020

Python的集合set原理

集合(set)是一个无序的不重复元素序列。

可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

class Array(object):

 def __init__(self, size=32, init=None):
  self._size = size
  self._items = [init] * self._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(len(self._items)):
   self._items[i] = value

 def __iter__(self):
  for item in self._items:
   yield item

class Slot(object):
 """定义一个 hash 表 数组的槽
 注意,一个槽有三种状态,看你能否想明白
 1.从未使用 HashMap.UNUSED。此槽没有被使用和冲突过,查找时只要找到 UNUSED 就不用再继续探查了
 2.使用过但是 remove 了,此时是 HashMap.EMPTY,该探查点后边的元素扔可能是有key
 3.槽正在使用 Slot 节点
 """
 def __init__(self, key, value):
  self.key, self.value = key, value

class HashTable(object):
 # 表示从未被使用过
 UNUSED = None
 # 使用过,但是被删除了
 EMPTY = Slot(None, None)

 def __init__(self):
  self._table = Array(8, init=HashTable.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)

 def _find_key(self, key):
  # 得到第一个值的位置
  index = self._hash(key)
  _len = len(self._table)
  # 当这个槽不是未使用过的,才接着往下找;如果是未使用过的,这个key肯定不存在
  while self._table[index] is not HashTable.UNUSED:
   # 槽使用过,但是被删除了
   if self._table[index] is HashTable.EMPTY:
    # cpython解决哈希冲突的一种方式
    index = (index*5 + 1) % _len
    continue
   elif self._table[index] == key:
    return index
   else:
    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)

 # 找到能被插入的槽的index
 def _find_slot_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

 # in 操作符
 def __contains__(self, key):
  index = self._find_key(key)
  return index is not None

 def add(self, key, value):
  if key in self:
   index = self._find_key(key)
   # 更新值
   self._table[index].value = value
   return False
  else:
   index = self._find_slot_insert(key)
   self._table[index] = Slot(key, value)
   self.length += 1
   if self._load_factor > 0.8:
    return self._rehash()
   return True

 def _rehash(self):
  oldtable = self._table
  newsize = len(self._table) * 2
  # 新的table
  self._table = Array(newsize, HashTable.UNUSED)
  self.length = 0
  for slot in oldtable:
   if slot is not HashTable.UNUSED and slot is not HashTable.EMPTY:
    index = self._find_slot_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):
  for slot in self._table:
   if slot not in (HashTable.UNUSED, HashTable.EMPTY):
    yield slot.value


class SetADT(HashTable):

 def add(self, key):
  return super(SetADT, self).add(key, True)

 def __and__(self, other_set):
  # 求交集
  new_set = SetADT()
  for element_a in self:
   if element_a in other_set:
    new_set.add(element_a)
  return new_set

 def __sub__(self, other_set):
  # 求差集
  new_set = SetADT()
  for element_a in self:
   if element_a not in other_set:
    new_set.add(element_a)
  return new_set

 def __or__(self, other_set):
  # 求交集
  new_set = SetADT()
  for element_a in self:
   new_set.add(element_a)
  for element_b in other_set:
   new_set.add(element_b)
  return new_set

以上就是Python 实现集合Set的示例的详细内容,更多关于Python 实现集合Set的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python mysqldb连接数据库
Mar 16 Python
Python中的MongoDB基本操作:连接、查询实例
Feb 13 Python
python 换位密码算法的实例详解
Jul 19 Python
Python贪心算法实例小结
Apr 22 Python
Python实现爬虫设置代理IP和伪装成浏览器的方法分享
May 07 Python
基于Python开发chrome插件的方法分析
Jul 07 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
Jul 27 Python
超简单使用Python换脸实例
Mar 27 Python
Python列表对象实现原理详解
Jul 01 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
Jul 11 Python
python 调试冷知识(小结)
Nov 11 Python
python能做哪些生活有趣的事情
Sep 09 Python
Python 实现二叉查找树的示例代码
Dec 21 #Python
如何利用Python matplotlib绘制雷达图
Dec 21 #Python
OpenCV+python实现膨胀和腐蚀的示例
Dec 21 #Python
python opencv肤色检测的实现示例
Dec 21 #Python
OpenCV+Python3.5 简易手势识别的实现
Dec 21 #Python
如何使用python-opencv批量生成带噪点噪线的数字验证码
Dec 21 #Python
python 录制系统声音的示例
Dec 21 #Python
You might like
PHP 读取和修改大文件的某行内容的代码
2009/10/30 PHP
Php Ctemplate引擎开发相关内容
2012/03/03 PHP
PHP 使用二进制保存用户状态的实例
2018/01/29 PHP
PHP替换Word中变量并导出PDF图片的实现方法
2020/11/26 PHP
Javascript操纵Cookie实现购物车程序
2006/11/23 Javascript
jQuery中获取Radio元素值的方法
2013/07/02 Javascript
Jquery插件分享之气泡形提示控件grumble.js
2014/05/20 Javascript
JS在可编辑的div中的光标位置插入内容的方法
2014/11/20 Javascript
jQuery中parent()方法用法实例
2015/01/07 Javascript
jQuery实现点击按钮弹出可关闭层的浮动层插件
2015/09/19 Javascript
jquery trigger函数执行两次的解决方法
2016/02/29 Javascript
Angular 根据 service 的状态更新 directive
2016/04/03 Javascript
js实现加载更多功能实例
2016/10/27 Javascript
js实现前端图片上传即时预览功能
2017/08/02 Javascript
详解ES6中的三种异步解决方案
2018/06/28 Javascript
如何使用electron-builder及electron-updater给项目配置自动更新
2018/12/24 Javascript
基于Vue插入视频的2种方法小结
2019/04/02 Javascript
详解Vue源码中一些util函数
2019/04/24 Javascript
jQuery加PHP实现图片上传并提交的示例代码
2020/07/16 jQuery
[03:36]2014DOTA2 TI小组赛综述 八强诞生进军钥匙球馆
2014/07/15 DOTA
python面向对象_详谈类的继承与方法的重载
2017/06/07 Python
Python中定时任务框架APScheduler的快速入门指南
2017/07/06 Python
python 3.0 模拟用户登录功能并实现三次错误锁定
2017/11/01 Python
Python中装饰器高级用法详解
2017/12/25 Python
pytorch permute维度转换方法
2018/12/14 Python
python读取txt文件中特定位置字符的方法
2018/12/24 Python
pycharm访问mysql数据库的方法步骤
2019/06/18 Python
python中的逆序遍历实例
2019/12/25 Python
解决python 在for循环并且pop数组的时候会跳过某些元素的问题
2020/12/11 Python
阿迪达斯希腊官方网上商店:adidas希腊
2019/04/06 全球购物
特色蛋糕店创业计划书
2014/01/28 职场文书
乡镇党员干部群众路线对照检查材料思想汇报
2014/09/28 职场文书
英文升职感谢信
2015/01/23 职场文书
超市采购员岗位职责
2015/04/07 职场文书
运动会加油稿50字
2015/07/21 职场文书
MySQL如何构建数据表索引
2021/05/13 MySQL