当前位置: 首页 > news >正文

做独立网站需要什么赣州seo唐三

做独立网站需要什么,赣州seo唐三,软件工程培训班多少钱,可以拿自己电脑做网站散列函数 算法不能设计太过复杂 太复杂的散列函数,势必会消耗很多计算时间 散列函数生成的值要尽可能随机并且均匀分布 这样才能避免或者最小化散列冲突而且即便出现来冲突,散列到每个槽里的数据也会比较平均,不会出现某个槽内数据特别多…

散列函数

算法不能设计太过复杂

  • 太复杂的散列函数,势必会消耗很多计算时间

散列函数生成的值要尽可能随机并且均匀分布

  • 这样才能避免或者最小化散列冲突
  • 而且即便出现来冲突,散列到每个槽里的数据也会比较平均,不会出现某个槽内数据特别多的情况

散列冲突

开放寻址法

概述

如果出现了散列冲突,我们就重新探测一个空闲位置,将其插入

优点

  • 开放寻址法不像链表法,需要拉很多链表
  • 散列表中的数据都存储在数据中,可以有效利用CPU缓存加快查询速度而且这样实现的散列表,序列化起来比较简单,链表法包含指针,序列化起来就没那么容易

缺点

  • 删除数据的时候比较麻烦,需要特殊标记已经删除掉的数据
  • 所有数据都存储在一个数组中,比起链表法来说,冲突的代价更高
  • 所有,使用开放寻址解决冲突的散列表,装载因子的上限不能太大。这也导致这种方法比链表法更浪费内存空间

方法

线性探测(Linear Probing)

当往散列表中插入数据时,如果某个数据经过散列函数之后,存储位置已经被占用了,我们就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止

二次探测(Quadratic probing)

线性探测每次探测的步长是1,那它探测的下标序列就是hash(key) + 0, hash(key) + 1, hash(key) + 2 …

而二次探测探测的步长就变成原来的“二次方”, 也就是说,它探测的下标序列就是 hash(key) + 0, hash(key) + (1 ^ 2), hash(key) + (2 ^ 2)

双重散列(Double hashing)

不仅要使用一个散列函数。我们使用一组散列函数 hash1(key), hash2(key), hash3(key)

我们先用第一个散列函数,如果计算得到的存储位置已经被占用,再用第二个散列,依次类推找到空闲的存储位置

装载因子(load factor)

不管采用那种方法,当散列表中空闲位置不多的时候,散列冲突的概率就会大大提高

为了尽可能保证散列表的操作效率,一般情况下,我们会尽快保证散列表中有一定比例的空闲槽位

状态因子概述及公式

散列表的装载因子 = 填入表中的元素个数 / 散列表的长度

装载因子来表示空位多少,状态因子越大,说明空闲位置越少,冲突越多,散列表的性能就会下降

如何解决装载因子过大的问题?

动态扩容

  • 重新申请一个更大的散列表,将数据搬移这个新的散列表中
  • 假设每次扩容我们都申请一个原来散列表大小两倍的空间。如果原来散列表的装载因子是0.8,那经过扩容之后,新散列表的装载因子因子就下降为原来的一半,变成了0.4

装载因子阀值的设置要权衡时间,空间复杂度

  • 如果内存空间不紧张,对执行效率要求很高,可以降低负载因子的阀值
  • 相反,如果内存空间紧张,对执行效率要求又不高,可以增加负载因子的值,甚至可以大于1

如何避免低效地扩容?

为了解决一次性扩容耗时过多的情况,我们可以将扩容操作穿插在插入操作的过程中,分批完成

当装载因子触达阀值之后,我们只申请新空间,但并不将老的数据搬移到新散列表中

当有新数据要插入时,我们将新数据插入新散列表中,并且从老的散列表中拿出一个数据放入新散列表中

每次插入一个数据到散列表,我们都重复上面的过程。经过多次插入操作之后,老的散列表中的数据就一点一点全部搬移到新散列表中

这时间的查询,为了兼容了新,老散列表中的数据,我们先从新散列表中查找,如果没有找到,再去老的散列表中查找

通过这样均摊的方法,将一次性扩容的代价,均摊到多次插入操作中,就避免一次性扩容耗时过多的情况。这种实现方式,任何情况下,插入一个数据的时间复杂度都是O(1)

链表法

概述

在散列表中,每个"桶(bucket)" 或者"槽(slot)" 会对应一条链条,所以散列值相同的元素我们都会放在相同槽位对应的链表中

当插入的时候,我们只需要通过散列函数计算出对应的散列槽位,将其插入到对应链表中即可,所以插入的时间复杂度O(1)

当查找删除一个元素时,我们同样通过散列函数计算出对应的槽,然后遍历链表查找或删除。那查找或删除操作的时间复杂度是多少呢?

  • 实际上,这两个操作的时间复杂度跟链表的长度k成正比,也就是O(k)
  • 对于散列比较均匀的散列函数来说,理论上讲, k = n / m,其中n表示散列中数据个数,m表示散列中“槽”的个数

优点

  • 链表法对内存的利用率比开放寻址法要高
  • 因为链表结点可以在需要的时候再创建,并不需要像开放寻址法那样事先申请好
  • 链表法比起开放寻址法,对大装载因子的容忍度更高
  • 开放寻址法只能适用装载因子小于1的情况
  • 接近1时,就可能会又大量的散列冲突,导致大量的探测,再散列等,性能会下降很多
  • 但是对于链表法,只要散列函数的只随机均匀,即便装载因子变成10,也就是链表的长度变长了而已,虽然查找效率有所下降,但是比起顺序查找还是快很多

缺点

  • 链表因为要存储指针,所有对于比较小的对象的存储,是比较消耗内存,还有可能会让内存的消耗翻倍
  • 而且,因为链表中的结点是零散分布在内存中,不是连续,所有对于CPU缓存是不友好的,这方面对于执行效率也有一定的影响
  • 总结
  • 基于链表的散列冲突处理方法比较合适存储大对象,大数据量的散列表
  • 而且,比起开放寻址法,它更加灵活,支持更多优化策略,比如用红黑树代替链表

工业级的散列表应该具有哪些特征?

要求

支持快速的查询,插入,删除操作

内存占用合理,不能浪费过多的内存空间

性能稳定,极端情况下,散列表的性能也不会退化到无法接受的程度

设计

设计一个合适的散列函数

定义装载因子阀值,并且设计动态扩容策略

选择合适的散列冲突解决方法

散列表的缺点和改进

缺点

  • 散列表这种数据结构虽然支持非常高效的数据插入,删除,查找操作,但是散列表中的数据都是通过散列函数打乱之后无规律存储的。也就是,它无法支持按照某种顺序快速地遍历数据
  • 如果希望按照顺序遍历散列表中的数据,那我们需要将散列表中的数据拷贝到数组中,然后排序,再遍历

改进

  • 因为散列表是动态数据结构,不停有数据的插入,删除,所以每当我们希望按顺序遍历散列表中的数据的时候,都需要先排序,那效率势必会很低
  • 为了解决这个问题,我们将散列表和链表(或跳表)结合一起使用
资料参考
  • [Data Structure & Algorithm] Hash那点事儿
http://www.ritt.cn/news/28136.html

相关文章:

  • wordpress轻系统网站优化靠谱seo
  • 什么网站专做外贸深圳百度快照优化
  • 网站开发下载那个2022百度搜索风云榜
  • 企业网站怎样做seo优化 应该如何做营销型网站建设解决方案
  • 郴州网站建设专业现状报告新人跑业务怎么找客户
  • 建设网站教程推广引流图片
  • 河南焦作有做网站开发的公司吗郑州疫情最新动态
  • 网站查询页面设计网站平台如何推广
  • wordpress logout某网站搜索引擎优化
  • 公众平台网站开发哪家好推广广告赚钱软件
  • 网站首页怎么做竞价托管多少钱一个月
  • 什么网站开发外贸客户注册网站怎么注册
  • 梁山网站建设百度一下首页网页百度
  • 优质网站建设关键词推广效果分析
  • 做网站开发哪里可以接单云南网站推广公司
  • 徐州网站建设方案开发北京seo排名外包
  • 做公益网站需要哪些部门认证推广普通话宣传内容
  • 门窗网站免费模板凡科网微信小程序
  • 网站线上推广方案南宁白帽seo技术
  • 杭州宣传片制作公司黑帽seo教程
  • 做黄色网站多少年在线资源搜索神器
  • asp网站源码说明百度一下 你知道首页
  • 网站开发和设计人员的岗位要求简单网页设计模板html
  • wordpress初始登录百度seo排名优化费用
  • 重庆网站建设有名 乐云践新强化防疫指导
  • iis做本地视频网站西安关键词排名推广
  • 政府网站集约化建设项目百度网页版电脑版
  • 政府网站建设联系电话软件开发公司经营范围
  • bbs网站设计培训网络营销机构
  • 做药的文献一般在哪些网站查找佛山seo培训