python内部查找表非常快,就是用的哈希表(hash-table)实现的。

后续实现字典集合。

怎么解决冲突?

其实一种直观的想法是如果冲突了我能不能让数组中 对应的槽变成一个链式结构呢?这就是其中一种解决方法,叫做链接法(chaining)。如果我们用链接法来处理冲突:

这样就用链表解决了冲突问题,但是如果哈希函数选不好的话,可能就导致冲突太多一个链变得太长,这样查找就不再是 O(1) 的了。

还有一种叫做开放寻址法(open addressing),它的基本思想是当一个槽被占用的时候,采用一种方式来寻找下一个可用的槽。 (这里槽指的是数组中的一个位置),根据找下一个槽的方式不同,分为:

线性探查(linear probing): 当一个槽被占用,找下一个可用的槽。

  • h(k, i) =

    % m, (i = 0,1,...,m-1 )

双重散列(double hashing): 重新计算 hash 结果。

  • h(k,i) =

    % m


二次探查(quadratic probing): 当一个槽被占用,以二次方作为偏移量。就是二次哈希。 (python使用的就是二次探查。)

  • % m , i=0,1,...,m-1
  • #注意:是在第一次得到的index上(+i*i) , 不是每次都累加。
inserted_index_set = set()#建立一个无重复集
M = 13 #键位13def h(key,M = 13):return key % Mto_insert = [765, 431, 96, 142, 579, 226, 903, 388]
#——————————————————————————————————————————————————————————————
for number in to_insert:index = h(number)first_index = index #得到first-index,如果发现这个键位被占用则计算下一个可用的键位。i = 1while index in inserted_index_set: #计算得到下一个可用的槽print('th({number}) = {number} % M = {index} collision' . format(number = number,index = index))index = (first_index + i*i) % M # 根据二次方探查的公式重新计算下一个需要插入的位置i += 1else: #没有被占用就直接输出print('h({number}) = {number} % M = {index}'.format(number = number,index = index))inserted_index_set.add(index)

output:

h(765) = 765 % M = 11
h(431) = 431 % M = 2
h(96) = 96 % M = 5
h(142) = 142 % M = 12
h(579) = 579 % M = 7h(226) = 226 % M = 5 collision
h(226) = 226 % M = 6h(903) = 903 % M = 6 collisionh(903) = 903 % M = 7 collision
h(903) = 903 % M = 10h(388) = 388 % M = 11 collisionh(388) = 388 % M = 12 collisionh(388) = 388 % M = 2 collisionh(388) = 388 % M = 7 collision
h(388) = 388 % M = 1

最终:

装载因子(load factor)

如果继续往我们的哈希表里塞东西会发生什么?空间不够用。这里我们定义一个负载因子的概念(load factor),其实很简单,就是已经使用的槽数比哈希表大小。 比如我们上边的例子插入了 8 个元素,哈希表总大小是 13, 它的 load factor 就是 8/13≈0.628/13≈0.62。当我们继续往哈希表插入数据的时候,很快就不够用了。 通常当负载因子开始超过 0.8 的时候,就要新开辟空间并且重新进行散列了。

重哈希(Rehashing)

当负载因子超过 0.8 的时候,需要进行 rehashing 操作了。

步骤就是重新开辟一块新的空间,开多大呢?感兴趣的话可以看下 cpython 的 dictobject.c 文件然后搜索 GROWTH_RATE 这个关键字,你会发现不同版本的 cpython 使用了不同的策略。python3.3 的策略是扩大为已经使用的槽数目的两倍。开辟了新空间以后,会把原来哈希表里 不为空槽的数据重新插入到新的哈希表里,插入方式和之前一样。这就是 rehashing 操作。

HashTable ADT

实践是检验真理的唯一标准,这里我们来实现一个简化版的哈希表 ADT,主要是为了让你更好地了解它的工作原理,有了它,后边实现起 dict 和 set 来就小菜一碟了。 这里我们使用到了定长数组,还记得我们在数组和列表章节里实现的 Array 吧,这里要用上了。

解决冲突我们使用二次探查法,模拟 cpython 二次探查函数的实现。我们来实现三个哈希表最常用的基本操作,这实际上也是使用字典的时候最常用的操作。

  • add(key, value)
  • get(key, default)
  • remove(key)

python 哈希表_数据结构-7 哈希表相关推荐

  1. 不同表结构数据迁移_数据结构:哈希 哈希函数 哈希表

    写在前面 希望你们看了能够有所收获,同时觉得不错的朋友可以点赞和关注下我,以后还会有更多精选文章分享给大家!大家可以关注一下java提升专栏 java提升​zhuanlan.zhihu.com 什么是 ...

  2. 人们通常先在线性表尾部临时添加一个_数据结构学习笔记-线性表

    我们经常会处理一系列类型相同的数据, 创建这种元素组, 读取和修改 当我们处理一个具有有穷或者无穷的元素数据集的时候, 我们需要将其作为一个整体来管理和使用, 用变量去表示它们, 传入和传出函数等等. ...

  3. python基础刷题_数据结构与算法LeetCode刷题(Python)

    参考资料: 一.链表 1.  链表的必备知识要点(包括基础知识.刷题中使用的STL等知识) 2.  链表逆序(LeetCode 92 ,206. Reverse Linked List 1,2) 3. ...

  4. mysql 线性表_数据结构之线性表

    概要 参考<大话数据结构>,把常用的基本数据结构梳理一下. 线性表 定义 线性表(List):零个或多个数据元素的有限序列. 若将线性表记为 \((a_1, \cdots, a_{i-1} ...

  5. java 实现内存数据表_数据结构 Java中的内存

    根据线性表的实际存储方式,分为两种实现模型: 顺序表 ,将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示. 链表 ,将元素存放在通过链接构造起来的一系列存储块中. 一.顺 ...

  6. python开源报表系统_流程设计器、表单设计器和简单报表管理开源OA系统smart-web...

    smart-web2是一套相对简单的OA系统:包含了流程设计器,表单设计器,权限管理,简单报表管理等功能: 系统后端基于SpringMVC+Spring+Hibernate框架,前端页面采用JQuer ...

  7. 线性表算法题库_数据结构与算法(线性表)练习题

    .word 资料 . 三.写一个算法合并两个已排序的线性表. (用两种方法:数组表示的线性表(顺序表)和 指针表示的线性表(链表) ) 要求: 1 .定义线性表节点的结构,并定义节点的型和位置的型. ...

  8. 哈希值 哈希码_什么是哈希? 哈希码如何工作-带有示例

    哈希值 哈希码 哈希简介 (Introduction to hashing) Hashing is designed to solve the problem of needing to effici ...

  9. excel链接隐藏工作表_自动隐藏Excel工作表

    excel链接隐藏工作表 When you build a workbook for other people to use, there might be worksheets that can s ...

最新文章

  1. Swift数组扩容原理
  2. 如何消费WCF Data Services定义的服务操作
  3. 给JDK报了一个P4的Bug,结果居然……
  4. 背后的故事之 - 快乐的Lambda表达式(二)
  5. springmvc知识点
  6. LeetCode 1116. 打印零与奇偶数
  7. arduino和python对接_Python:与Arduino进行交互-后续
  8. 无聊特意去拍月亮。呵呵
  9. 路径规划-人工势场法(Artificial Potential Field)
  10. SXF终端检测平台 EDR漏洞复现
  11. Outlook的服务器设置中POP3协议,在outlook的服务器设置中POP3协议是指
  12. 英文字体识别在线识别_如何查找和识别字体
  13. KERMIT,XMODEM,YMODEM,ZMODEM传输协议小结【转】
  14. 【一起学Rust】Rust的Hello Rust详细解析
  15. 实习6(持续更新)--数据分析
  16. 华为设备配置IS-IS命令
  17. Linux下的vim如何保存并退出
  18. 关于operator bool () 和bool operator ==()
  19. 大数据、云计算、物联网、数据仓库、OLAP、OLTP、等大数据你必须知道并且了解的概念及相关关系,我的一些总结
  20. element-ui时间组件使用

热门文章

  1. PostgreSQL与MySQL的日期类型DATE/date的格式区别
  2. jquery生成一个li_如何使用jQuery从字符串数组生成UL Li列表?
  3. 现代科技概论_现代科技概论课程:力与运动1
  4. Kotlin 接口(三)
  5. 这也许是Android一句话权限适配的更优解决方案
  6. python2.7更新pip_CentOS升级Python2.6到Python2.7并安装pip
  7. python sphinx_Python Sphinx使用实例及问题解决
  8. linux7本地yum安装,RHEL7安装本地离线yum源仓库
  9. 命令行开启一个unity实例和执行其中的脚本方法的使用和注意
  10. 在Web应用程序中执行常见搜索场景的服务器端方法