数据结构论坛

首页 » 分类 » 定义 » 从VBVBA字典Dictionary的算
TUhjnbcbe - 2023/6/16 20:55:00
福建白癜风医院 http://m.39.net/baidianfeng/a_4756241.html

1、Dictionary的查询速度很快,而且初始化后的Dictionary,的确很方便使用,于是开始挖掘出丰富的使用场景。甚至有网友将17万行Excel数据全部初始化到Dictionary中,每行新建1个Dictionary实例,所有行再嵌入到1个汇总Dictionary中,然后17万个Dictionary后,不让新建开始报错了。

2、通过内嵌Dictionary/Collection对象,的确可以构建出复杂的数据结构,用于应对复杂的数据场景。但像上例那样蛮用,很难体验这货的丝滑。究其原因就在于,没有了解清楚Dictionary本身的一些特性。

3、Dictionary内部是采用怎样的算法?结构又是怎样的?什么场景更适合?官方几乎没有透露相关信息。那么本篇,将简单地给大家介绍介绍,希望以后不要滥用Dictionary。

不难知道Dictionary内部核心就是HashTable,Hash故名思议就是信息摘要,将1个不定长度的信息,通过算法映射为固定长度的整数。Dictionary查询速度很快,其实查询使用的并非Key本身,而是其Hash值。而HashTable的算法核心,就是将这些Hash值再映射为数组的索引,最后通过索引进行查询。

从这里可以看出,Dictionary是构建在数组上的,当有人怀疑数组与Dictionary,谁的性能更好时,那么这里就是结论了。

4、简而言之,将不定长信息映射为1个固定长的整数过程,一般称之为摘要算法(也即Hash算法)。比如CRC系列算法,MD系列算法以及网络广为使用的SHA系列算法等。

Hash在计算机世界里有非常广泛的运用,比如文件的网络传输通常使用CRC值校验完整性,资源站(如百度云盘)通常使用MD5值标识文件(有时候从本地上传下载的电影啥的,能达到秒传,其实就是利用MD5检测到服务器已存在相应资源,只是给用户一个索引而已,自然快呀),互联网账号登录(如QQ)通常使用账号密码的Hash值代替账号密码进行校验来提升安全性等。

但是Hash算法本身就存在1个无法避免的漏洞:无限映射有限,就存在重复的可能,这就是碰撞。Hash算法本身不可逆,因此很多人将其作为密码算法来用,最为值得一提的,便是比特币一类的虚拟电子币。

其实这是很危险的,如果算力允许,最简单的穷举即可破解(找到碰撞子)。将Hash值作为验证手段,是建立在算力匮乏的假设上的,一旦算力得到解放,就会造成千年虫那样的影响。CRC/MD系列就是明证,比如我国的王小云通过特殊的算法设计,能大幅提高MD5等Hash的碰撞。而目前崭露头角的量子计算机,其算力已是目前最牛超算的数百万亿倍,比特币采用的sha,将很快迎来快速碰撞,重面CRC和MD系列的尴尬。到时,究竟谁会真正拥有比特币呢?互联网终端的肉鸡们?

扯远了,Dictionary中也存在Hash值冲突的情况,也就是相同的Hash值,可能对应好几个Key,这样映射的索引值却只有1个,也即多个Key去查询,返回相同的值,这不就是Bug了嘛。

5、为了解决这一问题,出现了诸多算法,其中链表法就是最常用的。链表法就像拉链一样,将冲突信息首尾串联在一起,整个链共享1个索引,当发生冲突时,就遍历这个链进一步比较信息,直到确认身份为止。制约HashTable(Dictionary)性能的,就在这个地方。

6、为了提高性能,有两个途径。一是设计出1个非常牛逼的Hash算法,对于任意数据样本都满足均匀分布,从而根本上减少冲突。二是扩大索引范围。很显然,后者更容易,这就是以空间换时间的经典场面。Dictionary也不例外,只不过相对比较折中,平衡了性能和内存开销而已。

7、那么Dictionary究竟开销如何呢?据BtOfficer测算,新建首个空的实例大约消耗K内存,此后每个新建空实例约占5K。这还没算每个键值对至少消耗的32字节,以及配套的Hash表扩张带来的消耗。所以,想想17万个Dictionary和N个数据对能占多少内存了吧,几乎能耗光用户可用的内存了。

8、综上,Dictionary其实并不适合大规模数据的处理,Dictionary胜在使用方便,符合人的直观,但这些都是有代价的。所以,能用数组,就直接用数组了。虽然VB/VBA中,数组也这样那样,比如前一篇讲的。

欢迎

1
查看完整版本: 从VBVBA字典Dictionary的算