业界动态
mfc 添加 excel类给定关键字不在字典中_python中的数据结构与算法(2):字典与集合
2024-11-19 03:12

字典是便于信息检索的一种数据结构,鉴于信息检索在程序中无处不在,字典的使用场景也非常广泛,包括许多 python 内部机制的实现,也依赖字典结构,比如命名空间的管理等。

mfc 添加 excel类给定关键字不在字典中_python中的数据结构与算法(2):字典与集合

检索一般是根据关键字查找与它关联的信息,这些关键字应该是固定的,否则就会使原来保存的数据失效,也就是说,关键字必须是不可变对象。当然,在具体实现上,我们知道,python 是根据是否存在 __hash__ 方法来判断一个对象是否可以作为关键字的,用户可以自行实现这个方法,但也承担相应的风险。

对于信息检索来说,效率往往是关键考虑因素。如果是一个静态字典,主要考虑的是创建和查找的效率问题,而对于更常用的动态字典来说,在其中插入和删除数据的效率也很重要。

下面,我们从使用者的角度看一下字典所需要支持的操作,然后简单讨论字典的实现技术。当然,它需要支持的操作决定了它应该采用的实现技术。


从使用者的角度,我可以梳理一下字典需要支持的操作。

python 字典提供了多种创建方式

在处理遍历时,python 提供了一个字典视图对象,这种对象提供的是一个动态视图。也就是说,如果字典的内容发生了变化,视图也会随之变化


显然,我们可以用列表来保存字典的键和关联的数据对象。

使用普通线性表时,数据检索的效率是 O(n) ,因为必须一一比对,直到找到键值,或者确定表中不存在该键值。如果我们改进结构,采用有序表,那么,通过二分法,可以以 O(logn) 的效率找到数据,是比较快的。不过,数据并不一定都可以排序,在实践中,甚至需要使用不同类型的对象作为字典的键,这时使用有序表就会遇到一些障碍。

而对数据插入和删除来说,基于线性表实现的字典在效率上是不能让人满意的。如果采用普通线性表,添加数据的时间复杂度是 O(1),删除数据则为 O(n);如果采用有序表,则插入和删除数据都是 O(n) 的时间复杂度。

线性表的另一个问题是需要连续的存储空间,对于规模较大的字典来说,也会造成一些困难。

总的来说,对于频繁变动,需要支持众多类型的键,或者规模较大的字典来说,线性表可能不是最好的选择。


树形结构是检索系统的常用数据结构。它不需要连续的存储空间,可以支持大规模的数据,如果设计科学,也可以实现高效的检索和修改。

理论上说,普通二叉树可以实现平均意义上的 O(logn) 检索效率和修改效率。但这种效率是没有保证的,如果没有及时控制和调整,普通二叉树很有可能在持续的数据变动过程中发生结构退化,某个分支无限延伸,导致检索和操作效率往 O(n) 靠近。

解决结构退化问题的思路,是在数据变动过程中,不断调整其结构,使其保持相对平衡。因此,在实践中可以采用平衡二叉树,或者红黑树,从而实现稳定的 O(logn) 的检索和操作效率。

如我们所知,除了二叉树,实践中也常常使用多分支排序树,或者说 N叉树。考虑到从磁盘读取数据时,其实是按块读取的,在一个节点上存储更多数据有利于减少磁盘读写操作,因此,多分支排序树在数据库系统中得到很好的应用。比如 MySQL 的 InNoDB 引擎,采用 B+ 树作为索引结构,如果以整数字段作为索引,每个节点大约可以有 1200 个分支。

当然,python 中的字典和集合采用的并不是基于树形结构的实现,而是基于哈希表的实现,在理想情况下,可以实现 O(1) 复杂度的检索和修改。


哈希表也叫散列表,本质上是一个线性表。线性表一定有一个下标区间,比如说一个可以存放 8 个元素的列表,其下标区间就是 0-7,如果我们可以设计一种函数,把字典的键映射为这个区间内的一个整数,就可以直接根据键计算得到它存储的具体位置,因而就可以实现快速访问和修改了,这个函数就是散列函数,或者哈希函数。

散列函数的设计有很多专业的研究,总的来说,它需要实现的基本性质包括

容易发现,采用散列表技术实现字典,会有两个绕不过去的问题

对于第一个问题,python 字典采用的空间扩展策略和列表的空间扩展策略类似。当我们创建一个空字典或者很小的字典时,初始分配的存储区可以容纳 8 个元素,当存储区的使用超过 2/3 时,字典会更换更大的存储区,并把之前保存的内容重新散列到新存储里。当元素个数低于 50000 个时,新扩展的存储区是原存储区的 4 倍,超过之后则调整为 2 倍。

为什么元素个数超过 2/3 就进行扩展呢?这个问题涉及到散列表的冲突处理技术。简单地说,由于 python 采用的是内部消解技术,为保持散列表的平均检索速度接近常数,需要控制其负载因子,也就是元素占空间可存储元素数量的比重低于 0.7 到 0.75。


哈希表一定会有哈希值冲突问题。比如说,一个可以存放 8 个元素的表,不同键计算得到的哈希值都是 5,这时该怎么处理呢

一种解决方案是使用外部空间,叫外部消解技术。比如说,对于所有出现冲突的键值,可以统一放到外部的某个列表,检索的时候,如果发现地址为 5 的空间存储的不是需要的键,就到外部列表查找,如果外部列表也没有找到,就判定这个键不存在。或者说,我们在哈希表中不直接保存对象(或者对象的引用),而保存一个列表的引用,所有哈希值为 5 的对象(或其引用)都保存在这个列表里等。具体实现可以采用多种不同的策略。

另一种解决方案是内部消解技术,也就是说,如果出现冲突,后进来的值依然会保存在内部空间,只是存储的位置做了调整。具体的调整策略可以多种多样,比如说,直接使用下一个空地址,或者再次进行散列操作等。这样,检索键值的时候,如果原有位置存储着其它键,就按规则继续检索,直到找到,或者遇到一个未使用的空间,从而判断该键不存在。

python 字典采用的是内消解技术。

不论如何,哈希值冲突都是我们希望尽量避免的,最坏情况下,所有键值都冲突,哈希表就会退化为一个线性表,数据检索复杂度会从 O(1) 上升为 O(n)。

事实上,由于哈希表必然出现冲突,因此在安全领域,有哈希碰撞攻击的思路。通过精心构造的、哈希值一致的数据,对同一个 API 发起请求,导致服务器 CPU 都消耗在数据检索上,无法快速响应请求,从而实现 DOS 的目的。


在 python 中,除了内置的字典,collections 模块还提供了另外两种常用的字典: defautdict 和 OrderDict。

defaultdict 实际上只是扩展了字典的 __missing__ 方法,支持用户提供一个 default_factory 函数,用于默认值的生成。当我们从字典取值时,如果字典没有对应的键,就会调用 __missing__ 方法,如果未定义这个方法,则直接返回 KeyError 。值得注意的是,__missing__ 方法不会被 __getitem__ 以外的方法调用,也就是说,如果我们使用 get() 函数取值,依然会返回指定的默认值或 None。

和常规字典相比,OrderDict 对象内部维护着一个根据键插入顺序排序的双向链表,新插入的元素会被放到链表的尾部,从而实现记住插入顺序的功能。不过,python3.7 版本之后,内置字典已经实现了一样的能力,并在 python3.8 版本提供了 __reversed__() 方法,因此,OrderDict 已经没什么存在的必要了。

进一步了解可以参考官方文档。


python 提供了两种内置集合类型:set 和 frozenset。它们的实现技术与字典是一致的,当然,frozenset 是不可变对象,其实现不需要考虑空间扩展的问题。

fronzenset 与 set 的关系有点类似于 tuple 与 list 的关系,形式上分为不可变和可变,底层技术基本一致,在实践中却往往用于完全不同的场景。

和字典不一样的地方在于,集合需要考虑数学中的集合类计算,如交集、并集、差集与对称差集等等。如果有兴趣,也可以直接查看官方文档。


    以上就是本篇文章【mfc 添加 excel类给定关键字不在字典中_python中的数据结构与算法(2):字典与集合】的全部内容了,欢迎阅览 ! 文章地址:http://fabua.ksxb.net/news/876.html 
     文章      相关文章      动态      同类文章      热门文章      栏目首页      网站地图      返回首页 海之东岸资讯移动站 http://fabua.ksxb.net/mobile/ , 查看更多   
最新文章
《实战十一人》12月20日内测开启
t2627_2_2627_1:4.0t1-t0:45.0t2-t1:4.0t3-t2:0.0t4-t3:2.0t5-t4:32.0t6-t5:14.0t7-t6:3.0t8-t7:0.0t9-t8:15.0t10-t9:0.0t11-t10
“报关骗局”阿里云客服《APP》软件无法提现是骗局吗,不正规能追回吗?
〖→被骗请点击进入帮助平台提现追款〗〖→被骗请点击进入帮助平台提现追款〗希望阅读此文的读者能够及时采取措施以减少损失;请
微信公众号点击菜单拉取消息事件推送如何操作?
2、注册成功后,通过用户名和密码登录微号帮平台,立即登录6、粉丝点菜单定时推送:推送信息设置7、推送信息设置:自定义弹出信
p站加速器哪个好?手把手教你怎么进P站?
老司机说的P站是什么?网上很多人都在说P站,而还有不少小白们不懂P站是什么意思,在网上也搜不到答案。其实,P站是有两层意思的
"码海拾贝-趣探1688:免费源码的狂欢"
一瞥眼,成品网站源码1688免费推荐,嘿,这话题不就跟那菜市场里挑挑拣拣的大妈一样,热热闹闹,沸反盈天?今儿个,科技圈里这档
哪些平台最适合进行广告推广?
在当今数字化时代,推广广告已成为企业营销战略的重要组成部分,选择合适的平台进行广告投放对于提高品牌知名度、吸引潜在客户以
东莞外贸建站推广,东莞外贸网站推广,东莞谷歌SEO优化
  在当今全球化的市场环境下,外贸企业越来越依赖于互联网来拓展业务和提高度。为了在激烈的竞争中脱颖而出,提高外贸网站在搜
maya快捷键大全
MAYA快捷键大全免费领取q群:289728818“独学而无友,则孤陋而寡闻!欢迎广大站友进群交流学习Enter 完成当前操作  ~ 终止当前操
外贸网站建设广告/百度下载电脑版
我开始使用 sklearn.naive_bayes.GaussianNB 进行文本分类,并且获得了很好的初始结果 . 我想使用分类器返回的概率作为置
优化博客seo的建议(优化博客seo的建议有哪些)
大家好,今天小编关注到一个比较有意思的话题,就是关于优化博客seo的建议的问题,于是小编就整理了7个相关介绍优化博客seo的建