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解析xml模块封装代码
Feb 07 Python
用Python编写一个每天都在系统下新建一个文件夹的脚本
May 04 Python
详解详解Python中writelines()方法的使用
May 25 Python
一个基于flask的web应用诞生 flask和mysql相连(4)
Apr 11 Python
python编写朴素贝叶斯用于文本分类
Dec 21 Python
python3.6使用pymysql连接Mysql数据库
May 25 Python
Python tkinter label 更新方法
Oct 11 Python
Python3实现的回文数判断及罗马数字转整数算法示例
Mar 27 Python
在Django model中设置多个字段联合唯一约束的实例
Jul 17 Python
Python3 批量扫描端口的例子
Jul 25 Python
python 实现在shell窗口中编写print不向屏幕输出
Feb 19 Python
pandas apply使用多列计算生成新的列实现示例
Feb 24 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定义参数数量可变的函数用法实例
2015/03/16 PHP
PHP的Json中文处理解决方案
2016/09/29 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
php使用goto实现自动重启swoole、reactphp、workerman服务的代码
2020/04/13 PHP
JQUERY THICKBOX弹出层插件
2008/08/30 Javascript
Riot.js 快速的JavaScript单元测试框架
2009/11/09 Javascript
jQuery学习笔记之jQuery动画效果
2013/09/09 Javascript
JavaScript中获取鼠标位置相关属性总结
2014/10/11 Javascript
jQuery实现非常实用漂亮的select下拉菜单选择效果
2015/11/06 Javascript
JS实现的数字格式化功能示例
2017/02/10 Javascript
JavaScript实现瀑布流以及加载效果
2017/02/11 Javascript
基于JS实现bookstore静态页面的实例代码
2017/02/22 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
JS简单实现滑动加载数据的方法示例
2017/10/18 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
2017/12/07 Javascript
修改vue+webpack run build的路径方法
2018/09/01 Javascript
nuxt中使用路由守卫的方法步骤
2019/01/27 Javascript
Layui 动态禁止select下拉的例子
2019/09/03 Javascript
layui 富文本编辑器和textarea值的相互传递方法
2019/09/18 Javascript
[02:05]2014DOTA2国际邀请赛 BBC外卡赛赛后总结
2014/07/09 DOTA
Python实现Tab自动补全和历史命令管理的方法
2015/03/12 Python
Python的math模块中的常用数学函数整理
2016/02/04 Python
用Python设计一个经典小游戏
2017/05/15 Python
python与C互相调用的方法详解
2017/07/14 Python
python 使用pandas计算累积求和的方法
2019/02/08 Python
《火烧云》教学反思
2014/04/12 职场文书
学生安全承诺书
2014/05/22 职场文书
校园安全标语
2014/06/07 职场文书
运动会加油口号
2014/06/07 职场文书
技术经济专业求职信
2014/09/03 职场文书
幼儿园教师师德师风演讲稿:我自豪我是一名幼师
2014/09/10 职场文书
大队委员竞选稿
2015/11/20 职场文书
小米11和iphone12哪个值得买?小米11对比iphone12评测
2021/04/21 数码科技
MySQL的安装与配置详细教程
2021/06/26 MySQL
为什么MySQL分页用limit会越来越慢
2021/07/25 MySQL
MySQL中的引号和反引号的区别与用法详解
2021/10/24 MySQL