范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Python数据结构与算法哈希map的实现及原理

  1-collections.MutableMapping
  1.1 概念:这是什么?
  大家可能想知道这一串英文是什么意思?其实只需要了解在collections库当中有一个非常重要的抽象基类MutableMappin
  g,专门用于实现map的一个非常有价值的工具。后边我们会用到它。
  2-我们的map基类
  2.1 实现这个类from collections import MutableMapping class Map(MutableMapping):     class _Item:         __slots__ = ("_key", "_value")          def __init__(self, key, value):             self._key = key             self._value = value         def __eq__(self, other):             return self._key == other._key         def __ne__(self, other):             return not (self == other)# 由于重写了__eq__,所以对象可以直接比较了(这里的==会执行__eq__)         def __lt__(self, other):# 小于             return self._key < other._value         # 一下三个方法其实均由上边eq、ne、lt得出         def __le__(self, other):# 小于等于             return self len(self._table)//2:#双倍扩容,常用的扩容方法,在之前用列表实现队列中提及过。             self._resize(2*len(self._table)-1)# 动态扩容     def __getitem__(self, item):# 索引 item是键         num = self._hash_zip(item)         return self._bucket_getitem(num, item)     def __delitem__(self, key):# 按键删除:其实hash也是映射容器,所以直观体现的就是键值对,而不是桶数组。         num = self._hash_zip(key)         self._bucket_delitem(num,key)# 这是真正的在桶数组中删除该键所映射的桶码中的对应元组,set和get同理         self._n -= 1     def _resize(self, length):# 扩容         old = list(self.items())         self._table = [None for x in range(length)]         self._n = 0         for (k,v) in old:             self[k] = v
  OK了,基本的哈希表就实现了,其实仔细想想很容易,但是自己要能实现还是要理解哈希表的本质哦,外加一定量的练习才可以熟练掌握,练习的目的就是为了熟练而已。
  5-分离链表实现的具体哈希map类
  说明:这玩意只是一种降低冲突的手段,上一节提过,降低冲突最好的地方是发生在元组进入桶的时候,所以想必大家猜到了,接下来的分离链表也就是为了self._bucket_xxxxxxx系列方法做准备。这里之所以在上边使用@abstractmethod就是为了继承实现,目的可以实现多种将冲突的哈希表。分离链表的概念上一节也有的。
  "见码入面"(借鉴:见字如面这个电视节目,有兴趣可以看看,还不错的):class ChainHashMap(HashMap):     def _bucket_getitem(self, hash_k, key):         bucket = self._table[hash_k]# 找到名字为hash_k的桶         if bucket is None:             raise KeyError("No such key in this hash_map")         return bucket[key]#桶中键为key的元组              def _bucket_setitem(self, hash_k, key, value):         if self._table[hash_k] is None:             self._table[hash_k] = UnsortedTableMap()#调用之前写的无序映射容器作为桶         oldsize = len(self._table[hash_k])# 插入元素前计算长度         self._table[hash_k][key] = value#_table[hash_k] 为其内部类_Item的对象,这里支持getitem方法,所以可以索引key         if len(self._table[hash_k]) > oldsize:#如果桶中新装了才加一,因为有可能是修改桶中元素,而非新增,修改的话_n不加1             self._n += 1      def _bucket_delitem(self, hash_k, key):# 这我感觉没啥好说的,很简单         bucket = self._table[hash_k]         if bucket is None:             raise KeyError("No such key in this hash_map")         self._table.remove(bucket)      def __iter__(self):         for bucket in self._table:#遍历桶数组中所有的桶             if bucket is not None:# 如果桶非空则                 for item in bucket:# 遍历非空桶中的元素,                                     # 桶为UnsortedTableMap的对象,而桶中的键值对又为其父类Map的内置类_Item的对象                     yield item
  6-用线性探测处理冲突的哈希map类
  这种方式的好处不需要再去借助其他额外的赋值结构来表示桶。结构更加简单。不会再像上一种方法还要让桶是一个UnsortedTableMap的对象。
  代码如下:class LineCheckMap(HashMap):     _FLAG = object()# 哨兵,或称标志位,主要用来描述某种特定的状态,     # 而在这里这个哨兵是为将删除的元素标志为其哨兵,减少删除带来的不必要的麻烦     # 其实用其他类型的值也行,这里只是为了和其他值区分     # 因为如下第一个可用桶要求是处女桶,导致那些被标志过得桶将会造成空间浪费。      def _is_avail(self, buck_num):# 判断桶是否空的(可用的)         #                    空桶                              已经删除过的桶         return  self._table[buck_num] is None or self._table[buck_num] is LineCheckMap._FLAG      def _find_slot(self, buck_num, key):# 找到存储元素的槽         first_avail_slot = 0#标志位,表示第一个可用的空桶         while True:             if self._is_avail(buck_num):# 如果桶可用                 if first_avail_slot == 0:# 如果第一个可用空桶为0                     first_avail_slot = buck_num# 将标志位更新为当前可用桶号                 if self._table[buck_num] is None:# 如果没找到该桶,则:                     return (False, first_avail_slot)# 返回错误和第一可用桶号             elif key==self._table[buck_num]._key:# 如果找到了桶元素所匹配的键                 return (True, buck_num)# 返回真和这个键所在的桶             buck_num = (buck_num+1)%len(self._table)# 线性探测的根本,参考上一节的描述,             # 同时你还会发现,这个算法思路和之前循环列表实现队列的思路很像      def _bucket_delitem(self, hash_k, key):         found, s = self._find_slot(hash_k, key)         if not found:             raise KeyError("No such key in this hash_map!")         self._table[s] = LineCheckMap._FLAG# 标志着桶中元素被删除了      def _bucket_setitem(self, hash_k, key, value):         found, s = self._find_slot(hash_k, key)         if not found:# 新增桶             self._table[s] = self._Item(key, value)#Item是HashMap父类Map的内置类             self._n += 1         else:# 旧桶改值             self._table[s]._value = value      def _bucket_getitem(self, hash_k, key):         found, s = self._find_slot(hash_k,key)         if not found:             raise KeyError("No such Key in this hash_map")         return self._table[s]._value      def __iter__(self):         for item in range(len(self._table)):             if not self._is_avail(item):                 yield self._table[item]._key
  这篇文章连写带讲解,费了4个小时的时间,真的是很少有机会能如此浸入式地写作,说明这篇内容确实还是有点东西的,整理加上反复咀嚼确实理解很有趣,很有意思,希望各位在我总结的基础上,好好理解下,毕竟如果你程序员做久了,这些东西都是大同小异基本固定的代码,但是数据结构和算法的重点在理解其实现原理,这个才是很重要的地方,不要走偏了,不要觉得会背或者记住了这一种代码,那是没用的,必须要理解,逐层慢慢理解,对于初学者,这篇文章静下心来可能需要10个小时左右去理解和挖掘,所以每一步我都会尽我所能把我理解的传输给各位,但是理解难免有不同之处,每个人看事物的方式都不同,所以各位,尽量看,尽量理解,不要在意那些错别字,这个不是重点。如果究其有几个错别字,那我建议还是学文学吧。声明,上文中提及的代码都是有固定套路的,不存在谁抄袭谁的问题,要是了解过一点数据结构的,一眼就能看出代码是套路化的东西,重点请仔细理解我写的每句注释!!!这个很重要,方便你们真的理解这个概念,数据结构,本来在乎的就不是代码怎么写,在乎的都是,你是否有这种数据结构的蓝图在脑海中,随时可以即兴提笔来上一段自己的sao操作,这就是编程的乐趣。

小鹏汽车开启中国品牌出海2。0模式新年伊始,我们的出海业务迎来双喜临门。近日,小鹏汽车宣布与欧洲头部经销商集团荷兰EmilFreyNV集团()以及瑞典Bilia集团()达成战略合作协议,旨在推动小鹏汽车快速导入当地骨传导耳机到底有哪些优势,体验完飞利浦A6606骨传导耳机我悟了春天到了,想必很多人都和我一样又想出门运动了吧!而出门运动,必不可少的装备一定是运动耳机了,毕竟在运动过程中有音乐的加入,也能让我们更好的跟着音乐动起来。但常规的运动耳机麻烦不少,这7个免费的微信小程序,却把收费软件的活都干了其实微信上有很多小程序完成可以代替手机APP,不用下载就可以直接使用,下面分享7个免费的微信小程序,却把收费软件的活都干了。1吐司工具箱APP有百宝工具箱,其实小程序也有,吐司工具手机厂商都在吹捧双摄,为什么上万元的相机却不用双摄?首先纠正下问题,原来也有很贵的双镜头相机(其实也不是双摄),现在还有人在玩。单反相机大家都知道,有单必有双,这个双镜头相机就叫双反相机,就是下面这样,现在被淘汰了。好了,回到问题,鸿蒙系统华为手机,你们会支持吗?肯定支持!我现在用的就是华为V10,2200元,差不多两年了。我觉得这手机还是蛮好用的,也许与装的东西少吧!挨着身体还是有点热,行内人士都说这是正常的。三星没用过,苹果买不起。所以最强中国芯天玑9000登场,高通骁龙8Gen1,还香吗,咋选?没有谁会吧联发科当做中国芯。海思麒麟才是真正的中国芯。这点毋庸置疑。联发科跟台积电一样都只是美帝控制的一个棋子而已海思麒麟才是真正的中国芯,希望华为早日解决代工问题,发哥不算是中国买华为Mate40pro8256还是买荣耀至臻12512?都不买,这俩安处理器都是落伍了,都不喜欢。40好些吧作为都使用过的过来人,强烈建议华为。从体验来看,两者硬件和系统流程度差不多,但至臻的摄像AI技术赶华为差几条街,而且一直未有改进美媒加密货币使得俄罗斯更容易规避制裁澎湃新闻记者南博一实习生卢之琳近日,据美国媒体报道,一些区块链专家表示,西方对俄罗斯实施的金融制裁措施变得越来越容易被规避,部分原因是俄罗斯正大量采用加密货币。据美国有线电视新闻网俄罗斯战争引发货币担忧,乌克兰比特币交易量飙升200大家好我是币圈小沫沫Kuna是一家长期运营的本地加密货币交易所,在货币管制和格里夫纳处于历史低位的情况下,客户活动发生了迅速变化。数据显示,在俄罗斯入侵后,乌克兰一家主要加密货币交数字货币将会在东数西算下出现超级大行情今年开年,国家推出重磅发展战略东数西算,大力发展东部的数据中心和西部的算力中心。目的是在国家层面上统筹算力资源和数据资源,在数字经济时代发挥最为强大的合力。作为投资者,要对于这些新Python面向对象编程之封装的艺术1。面向对象编程OOP(ObjectOrientedProgramming)即面向对象编程。面向对象编程是一种编码思想,或是一种代码组织方式。如同编辑文章时,可以选择分段分节的方式
Win10最好用的功能,只有1的人会正确使用进命令提示符或BIOS修改电脑软硬件设置时,进安全模式杀毒删文件卸载软件排查问题时系统文件损坏进不了系统,需要修复或重置时,更新后出现没声音键鼠不能用等异常,需要卸载更新时我们常提环比增长26!OPPO进入全球出货量TOP5全靠这几招最近,权威调研机构Counterpoint公布第三季度的全球手机市场份额调研报告,在这份行业公信力榜单上,我们看到了不少熟悉的国产手机品牌,而作为国内一线大厂的OPPO,这次也位列黑格增长助力你避开Facebook上的雷区,高效获客Facebook作为全球最成功的社交平台,有超过27亿月活跃用户,很多人或许对这个数字没有什么概念,那么如果我说微信的用户量为12亿,这样对比起来,可能大家就对Facebook客户高端梦再次破碎,联发科的未来你怎么看?今年是5G快速发展的关键时期。手机市场的竞争最为明显。为了抢占市场份额,主要制造商疯狂地推广5G手机。当然,这个目标也已经实现。最重要的是,主要制造商希望进入高端市场并顺应当前趋势饭店自动洗碗机的特点及注意事项中大型洗碗机适用于繁忙的大型食堂。与人工洗碗机和其他洗碗机不同,重复的工作可能会降低人工工作效率,而其他洗碗机可能无法清洁这么多餐具,从而降低清洗质量。大型洗碗机每小时可清洗960案例解读2020外贸独立站运营效果如何?几乎全世界,包括中国人,在年初都没有想到,2020会以这样一种全球疯买中国货的方式收官。据数据显示,2020年11月,中国的出口增速21。1,贸易顺差754亿美元,创下了自1981黑格增长拍了拍你,客户的联系方式还有三秒抵达你是否还在担心找不到途径获客?客户联系方式太单一?与客户沟通受到阻碍?客户流失加重?HaGro黑格增长助力多种渠道让你成功获客实现社交平台红利裂变式增长!自从疫情爆发以来,跨境贸易教你SEMrush的正确打开方式,获取有价值的谷歌推广关键词之前有遇见这样的一个情况一个老板上来,就给新来的SEO专员布置了一个任务1个月之内把trademarkregistration这个词做到谷歌首页。你们认为这个SEO专员会怎么办?该交换机的管理方式(一)Telnet管理一首先配置服务机(1)进入配置需要打的三条命令undoterminalmonitor关闭弹出信息systemview用户视图进入系统视图查看,调试sysname重命名(2)进入虚拟Linux系统基本命令和快捷方式一如何连接shellIrootalocalhostIvimetcsysconfignetworkscriptsifcfgens33回车一下BOoTPROTOstatic网卡获取地址不做谷歌SEO的外贸企业,正在错失这些出海优势外贸推广,会选择什么渠道?B2B平台,展会社媒广告还是独立站?独立站在近两年来迎来了一个高速爆发期,很多企业选择自立门户开展谷歌独立站营销。如果你认为的独立站只是一个展示作用,那么