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

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操作,这就是编程的乐趣。

中关村相关领导发表致敬倪光南究竟透露出了什么信号?这是中关村原领导对柳传志义愤填膺的控诉,对老一辈科学家倪光南院士的不幸遭遇给予了极大的同情。一个抛弃国外高薪报酬专心致志为国效力汉卡之父和联想电脑之父倪光南院士却被柳传志扫地出门,12。18日半导体,光伏,白酒,新能源汽车,特高压,生物医药半导体,光伏,白酒,新能源车,特高压,生物医药行业下周怎么走?1半导体行业本周受到消息面利空影响,跌幅较大。同时跌破多周期均线,周五的这根放量大阴线也比较难看。指标上,周线日线均有全民K歌用什么设备录制效果会更好?感谢邀请,本人就来说说我的全民K歌录歌的观点,当然之前也玩了三年多了,如果我们想录制好一首歌,要做得更好,当然必须要有一款带声卡的麦克风,网上也有的卖,一般几十块到几百块都有,当然各国争相进行战略布局抢占发展先机,元宇宙为何这么火?近年来,随着5G云计算等数字技术的加速发展,数字经济已经成为促进生产方式转型升级,推动新业态新模式发展的重要动力。在移动互联网时代增长红利递减的背景下,元宇宙作为整合多种新技术而产新能源充电桩6大重点方向,来年有望成为高成长的潜力股前几天的JJ重要会议指出,要重点聚焦重点方向。为保持政策的延续性和稳定性统筹做好今明两年宏观政策的衔接,明确了2022年专项债用于9个大的方向,其中第一点是交通基础设施,二是能源等SpaceX星链布局远超预期全球卫星互联网建设或加速卡位国内千亿规模市场蓄势待发财联社(上海,编辑陈默)讯,SpaceX猎鹰9号火箭在加利福尼亚州范登堡太空军基地发射52颗星链卫星,诞生首枚一箭11飞火箭。自2019年5月首批60颗星链卫星上天以来,Space储能特斯拉新能源锂电池石墨烯!石墨负极出货量多年全球第一储能特斯拉新能源汽车锂电池石墨烯!全球锂电负极龙头深度绑定宁德时代,石墨负极出货量多年全球第一,投建10万吨相关项目机构预估今明两年净利均翻番!这家细分龙头25亿元投建10万吨锂电数据分析与埋点,产品经理必须掌握的知识和技能产品经理必须随时全面而准确地了解自己产品的各项数据,否则只能凭着感性在规划和设计产品,容易犯错误。因此,看哪些数据,如何统计和分析数据,如何进行数据埋点,都是产品经理必须要掌握的知为什么超50的专精特新小巨人企业,都在用钉钉?我们使用钉钉低代码平台已有3年时间了,它的门槛特别低,看新手教程就可以明白怎么用。在深圳前海的一栋写字楼里,邱康华正在介绍他的日常工作如何通过钉钉进行项目管理。邱康华是影石创新的内社区团购飞速增长,资本竞相入局易观分析微信小程序的成熟化,下沉市场消费群体对生鲜的需求提升,催生了社区团购市场的爆发式增长。VC产业资本互联网巨头等亲自下场,市场掀起来新一轮的社区团购大战,市场乱象恶行竞争此起生鲜社区店应该怎么做饭饭平台做社区的优势近些年来传统零售商超越来越不好干以是不争的事实,尤其是在销售上面,由于互联网经济的介入,实体零售经济愈发萎靡,而生鲜商超等则在实体经济走低的浪潮里举步维艰。然而现如今,敢于入局利用
别墅装修设计技巧,快来看别墅装修的费用不是固定的,主要还是看你所选得装修档次,业主对于别墅装修费用预算也不知道大概要准备多少钱,这是大多数业主都想要知道的1简单装修别墅如果采用简单方式来装修的话,业主就是投资创历年新高,全球商业航天进入新时代资本实验室今日投资关注聚焦前沿科技创新与传统产业升级人类对太空的探索正在进入从未有过的最雄心勃勃最热情高涨的时期。嫦娥四号传回人类首张月背影像图中国民营航天运载火箭首次成功发射并高未来十年将颠覆现代商业格局的七种新兴商业模式资本实验室今日创新观察聚焦前沿科技创新与传统产业升级张珂在传统商业体系中,基于用户心理和消费行为,诞生了很多创新型的商业模式。例如,1920年代出现的饵与钩模式,利用低价产品吸引用2年干了18亿,方太式增长,值得业内企业研究和学习如果时至今日,还有哪个单品品牌没有意识到整装渠道重要性的,那你可能真的要小心了,因为未来的角逐中,很可能已经没有你位置,甚至连后起直追的机会都不会给你。未来商业智库首席专家中国泛家4年内数字业务占比超过50英国卫报如何成功转型?在互联网时代,受到新媒体的冲击,全球众多传统纸媒纷纷倒闭或转型。尽管数字化是唯一的出路,但转型成功的媒体屈指可数,而英国卫报则是其中的典型之一。英国卫报创办于1821年,是英国主流美初创公司CFS正推动清洁聚变能源技术的商业化资本实验室李鑫美国新能源初创公司CommonwealthFusionSystems(简称CFS)成立于2017年,衍生于美国麻省理工学院,致力于聚变能源的商业化,并向世界提供无限的全球创新观察5月刊发布全球技术博弈又有新动作在百年未有之大变局和疫情的叠加冲击下,国际政治世界经济全球治理等遭受重大冲击。最新发布的全球创新观察研究报告(5月刊)中指出,在疫情打击和中美贸易关系更趋紧张的大背景下,过去数十年美国4月零售额下跌创纪录,传统零售企业正迎来倒闭潮资本实验室李鑫电子商务的快速发展大幅压缩了传统零售企业的生存与发展空间。随着新冠肺炎在全球蔓延,更让众多传统零售商雪上加霜。据美国人口普查局的数据显示,美国4月份零售额环比下降16工业巨头大踏步转型一文看清JioPlatforms的130亿美元融资资本实验室冉伟近期,印度电信公司JioPlatforms获得约130亿美元融资的消息引发了全球关注。我们对相关的关键信息进行梳理和分析如下1。JioPlatforms是一家什么样的6月全球区块链典型应用趋势分析资本实验室今日创新观察聚焦前沿科技创新与传统产业升级据国创会创新院与资本实验室不完全统计,2020年6月全球典型区块链应用案例共161起。其中,数据共享溯源安全领域90起,政务非盈Neo3海报曝光865144Hz4500mAh?iQOONeo3线下预定海报显示其价格为2998元,主打高通骁龙865支持双模5G,144Hz竞速屏,4500mAh电池容量,双扬声器等等至于其他配置,据了解iQOONeo3提供夜