ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

读数据结构与算法之美(四)

2022-02-20 10:05:54  阅读:195  来源: 互联网

标签:装载 之美 列表 链表 算法 二叉树 数据结构 散列 节点


4.散列表&哈希&树

18 - 散列表(上):Word文档中的单词拼写检查功能是如何实现的?

散列表:Hash Table,又称哈希表,或者hash表。

散列表,用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,没有数组就没有散列表。

关键字:键(key)、哈希函数、散列值(value)

哈希函数的三个基本要求:

1.散列值是一个非负正数

2.key1==key2 则hash(key1)==hash(key2)

3.key1!=key2 则hash(key1)!=hash(key2)

第三点几乎不可能。无法避免散列冲突。

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

解决散列冲突的方法:

1.开放寻址法、2.链表法

19 - 散列表(中):如何打造一个工业级水平的散列表?

散列表的查询效率并不能笼统的说成是O(1)。它跟散列函数、装载因子、散列冲突等都有关系。

如果散列函数设计的不好,或者装载因子过高,都可能导致散列冲突发生的概率升高,查询效率下降

散列函数的设计,不能太复杂。

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

装载因子过大了怎么办?

可以进行动态扩容。重新申请一个更大的散列表,将数据搬移到这个新散列表中。

装载因子阀值需要选择得当。如果太大,会导致冲突过多;如果太小,会导致内存浪费严重。

如何避免低效的扩容?

当装载因子已经到达阈值,需要先进行扩容,再插入数据。这个时候插入数据就会变得很慢,甚至会无法接受。

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

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

对应查询操作,先从新散列表中查找,如果没有找到,再去老的散列表中查找。

通过均摊的方法,将一次性扩容的代价均摊到多次插入操作中。

开放寻址法VS链表法

当数据量比较小、装载因子小的时候,适合采用开放寻址法。这也是java中ThreadLocalMap使用开放寻址法解决散列冲突的原因。

链表法比较适合存储大对象、大数据量的散列表,而且它更加灵活,支持更多的优化策略,比如用红黑树(或者跳表)代替链表。

举例分析HashMap

1.初始大小

2.装载因子和动态扩容

3.散列冲突解决方法

4.散列函数

20 - 散列表(下):为什么散列表和链表经常会一起使用?

链表实现的LRU缓存淘汰算法的时间复杂度是O(n),通过散列表可以将这个时间复杂度降低到O(1)。

Redis的有序集合不仅使用了跳表,还使用了散列表。

LRU缓存淘汰系统

一个缓存系统主要包含下面几个操作:

1.往缓存中添加一个数据

2.从缓存中删除一个数据

3.在缓存中查找一个数据

这3个操作都要涉及“查找”操作,如果单纯地采用链表的话,时间复杂度只能是O(n)。

如果将链表和散列表组合使用,可以将这3个操作的时间复杂度降低到O(1)。

23 - 二叉树基础(上):什么样的二叉树适合用数组来存储?

满二叉树:叶子节点都在最底层,除了叶子节点之外,每个节点都有左右两个子节点。

完全二叉树:叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大。

满二叉树,又是完全二叉树的一种特殊情况。

如何表示(或存储)一颗二叉树?

1.基于指针(或者引用)的二叉链式存储法

2.基于数组的顺序存储法

如果某棵二叉树是一棵完全二叉树,那用数组存储无疑是最节省内存的一种方式。

这也是为什么完全二叉树会单独拎出来的原因,也是为什么完全二叉树要求最后一层的子节点都靠左的原因。

二叉树的遍历

1.前序遍历:打印自己→左子节点→右子节点

2.中序遍历:左子节点→打印自己→右子节点

3.后序遍历:左子节点→右子节点→打印自己

 

24 - 二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?

1.散列表中的数据是无序存储的,如果要输出有序的数据,需要先进行排序。而二叉查找树的中序遍历,可以在O(n)的时间复杂度输出。

2.散列表扩容耗时很多,散列冲突时性能不稳定。二叉查找树性能也不稳定,但是平衡二叉查找树的性能非常稳定,时间复杂度O(logn)

3.哈希冲突以及哈希函数的耗时,性能不一定高

4.散列表的设计比较复杂

标签:装载,之美,列表,链表,算法,二叉树,数据结构,散列,节点
来源: https://blog.csdn.net/wen3qin/article/details/123027447

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有