少年,不知道你好记不记得第三篇文章讲python内建数据结构的方法及其时间复杂度时里面关于dict与set的时间复杂度[为何访问元素为O(1)]原理我说后面讲吗?其实就是这篇文章讲啦。
目录:
一:Hash的定义
二:dict与set的实现原理
三:常用构造hash函数的方法
四:hash碰撞及其解决方法
五:dict的实现
一:Hash的定义
Hash,一般翻译做“散列”,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。【不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值】
二:dict与set的实现原理
dict与set实现原理是一样的,都是将实际的值放到list中。唯一不同的在于hash函数操作的对象,对于dict,hash函数操作的是其key,而对于set是直接操作的它的元素,假设操作内容为x,其作为因变量,放入hash函数,通过运算后取list的余数,转化为一个list的下标,此下标位置对于set而言用来放其本身,而对于dict则是创建了两个list,一个list该下表放此key,另一个list中该下标方对应的value。
其中,我们把实现set的方式叫做Hash Set,实现dict的方式叫做Hash Map/Table(注:map指的就是通过key来寻找value的过程)
三:常用构造hash函数的方法
1:折叠法
将每个元素分为相等的几部分后相加后再除以list长度,e.g:如果项目是436-555-4601, 以2为分组,分成了 (43, 65, 55, 46, 01). 全部加起来:43 + 65 + 55 + 46 + 01 = 210. 假设list有11个元素, 则210%11 =1, 所以将436-555-4601放到list下标为1的地方。
2:取中法:
如元素44平方后得1936取中93再取list的余
注:对于string其所对应的数字可用其ASCII码来代替(还可与位数结合,见图5.7)ord('a')可返回'a'的ASCII码
注:此地就是为什么dict与set访问元素时间复杂度为O(1)的原因了,通过对元素的hash函数运算后能够直接知道其下标,所以为O(1)
四:hash碰撞及其解决方法
定义里面讲到过不同的输入可能会散列成相同的输出,所以就可能出现名为“哈希碰撞”的情况,也就是说两个不同的元素算出来的下标值一样,此时就有两种解决方法:
1:向后探测
架设一个元素算出来下标为5,另一个元素算出来下标也为5,从开头开始探测第0第1位是否为空,当看到为空的就放入,不过这样相邻探测的不好之处在于容易发生聚集,所以最好是跳跃着进行探测,定义一个skip的值,比如3,用方程rehash(pos) = (pos + skip)%sizeoftable,即使查看0,3,6这样跳跃着来
2:链式存储
原理图如下,其实就是将发生有冲突的元素放到同一位置,然后通过“指针“来串联起来
五:HashTable
下面将写一个hashTable,而实际中的dict就是由hashTable扩展而来的
class HashTable:
def __init__(self):
self.size = 11
self.slots = [None] * self.size
self.data = [None] * self.size def hash_function(self, key, size):
return key % size
def rehash(self, old_hash, size):
return (old_hash + 1) % size
def __getitem__(self, key):
return self.get(key)
def __setitem__(self, key, data):
self.put(key, data) def put(self, key, data):
hash_value = self.hash_function(key,len(self.slots))
if self.slots[hash_value] == None:
self.slots[hash_value] = key
self.data[hash_value] = data
elif self.slots[hash_value] == key:
self.data[hash_value] = data # replace
else:
next_slot = self.rehash(hash_value, len(self.slots))
while self.slots[next_slot] != None and self.slots[next_slot] != key:
next_slot = self.rehash(next_slot, len(self.slots))
if self.slots[next_slot] == None:
self.slots[next_slot] = key
self.data[next_slot] = data
else:
self.data[next_slot] = data #replace def get(self, key):
start_slot = self.hash_function(key, len(self.slots))
data = None
stop = False
found = False
position = start_slot
while self.slots[position] != None and not found and not stop:
if self.slots[position] == key:
found = True
data = self.data[position]
else:
position=self.rehash(position, len(self.slots))
if position == start_slot:
stop = True
return data
HashTable
python 下的数据结构与算法---8:哈希一下【dict与set的实现】的更多相关文章
-
python 下的数据结构与算法---1:让一切从无关开始
这段时间把<Data Structure and Algorithms with python>以及<Problem Solving with Algorithms and Dat ...
-
python 下的数据结构与算法---4:线形数据结构,栈,队列,双端队列,列表
目录: 前言 1:栈 1.1:栈的实现 1.2:栈的应用: 1.2.1:检验数学表达式的括号匹配 1.2.2:将十进制数转化为任意进制 1.2.3:后置表达式的生成及其计算 2:队列 2.1:队列的实 ...
-
python 下的数据结构与算法---6:6大排序算法
顶先最后推荐:哈哈,意思是放到顶部强调其重要性,但是应该我总结的六种算法看完了后再看的一篇醍醐灌顶的文章 一:冒泡排序(Bubble Sort) 原理:假设有n个数,第一轮时:从第一个元素开始,与相邻 ...
-
python 下的数据结构与算法---3:python内建数据结构的方法及其时间复杂度
目录 一:python内部数据类型分类 二:各数据结构 一:python内部数据类型分类 这里有个很重要的东西要先提醒注意一下:原子性数据类型和非原子性数据类型的区别 Python内部数据从某种形式上 ...
-
python 下的数据结构与算法---2:大O符号与常用算法和数据结构的复杂度速查表
目录: 一:大O记法 二:各函数高阶比较 三:常用算法和数据结构的复杂度速查表 四:常见的logn是怎么来的 一:大O记法 算法复杂度记法有很多种,其中最常用的就是Big O notation(大O记 ...
-
python 下的数据结构与算法---7:查找
一:线性查找(Sequential Search) 线性查找可以说是我们用的最早也会是用的最多的查找方式了.其对应的是线性数据结构,回顾一下线性数据结构,其特点是先后加入的元素是有顺序的,相邻的.而线 ...
-
python 下的数据结构与算法---5:递归(Recursion)
定义:递归就是不断分割整体成部分直到可以轻易解决分割出来的部分. 递归表达式三定律: 1:递归表达式必须有个最小单元 (最小单元既是停止递归调用以及能够直接运算的) 2:递归表达式在运算过程中 ...
-
Python实现的数据结构与算法之队列详解
本文实例讲述了Python实现的数据结构与算法之队列.分享给大家供大家参考.具体分析如下: 一.概述 队列(Queue)是一种先进先出(FIFO)的线性数据结构,插入操作在队尾(rear)进行,删除操 ...
-
用Python实现的数据结构与算法:开篇
一.概述 用Python实现的数据结构与算法 涵盖了常用的数据结构与算法(全部由Python语言实现),是 Problem Solving with Algorithms and Data Struc ...
随机推荐
-
使用Guava EventBus构建publish/subscribe系统
Google的Guava类库提供了EventBus,用于提供一套组件内publish/subscribe的解决方案.事件总线EventBus,用于管理事件的注册和分发.在系统中,Subscribers ...
-
codeforces 732/D 二分
给出考试时间和考试需要准备的时间,问最早考完所有科目的时间 二分答案 NlogN 二分抄神犇的写法 感觉挺舒服的嘻嘻嘻 #include<bits/stdc++.h> using name ...
-
【BZOJ3675】序列分割(斜率优化,动态规划)
[BZOJ3675]序列分割(斜率优化,动态规划) 题面 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得 ...
-
idea右键无法生成javaclass
博客转自:https://www.cnblogs.com/zjfjava/p/9219237.html 项目中新建目录之后,要在该目录下新增java Class文件,右键——>New发现无对应选 ...
-
Neutron vxlan network--L2 Population
L2 Population 是用来提高 VXLAN 网络 Scalability 的. 通常我们说某个系统的 Scalability 好,其意思是: 当系统的规模变大时,仍然能够高效地工作. L2 ...
-
Maven项目强制更新,解决Failed to read artifact descriptor for xxx.jar问题
导入的maven项目pom.xml现红叉 分析原因:在maven本地仓库中找不到相应的jar包. 解决方案:让maven强制更新依赖. 项目右击菜单,Maven -> Update Projec ...
-
skynet记录6:定时器
稍后填坑 kernel中,每一次时钟中断会trap到kernel code,这个时间间隔称之为jiffies,每秒钟发生的次数为HZ 如果是4核,分配到每个核就是HZ/4 cat /boot/conf ...
-
XSS漏洞解析(一)
以前写程序没有怎么关注这些网络安全问题,随着自己写的程序越来越多,开始关注了网络安全了. 一.什么是XSS XSS(Cross-Site Scripting) 跨站脚本是一种经常出现在web应用程序的 ...
-
写一个ORM框架的第一步(Apache Commons DbUtils)
新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...
-
【转】深入理解Java中的final关键字
Java 中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了 什么?使用final的好处是什么?最后也有一 ...