![0f19f1980eada99ad045ebeb6a1183ee.png](https://i-blog.csdnimg.cn/blog_migrate/53fe54da9631d33bee454ed34b788045.jpeg)
熬夜写代码
关注公众号:EZ大数据。
每天学习一点点,不亏!
"
世界上最重要的事情是理解现实如何运行,一级如何应对现实。面对这一过程的心态至关重要!
——达利欧《原则》
"
昨天说完二叉搜索树,今天来个简单点的:集合Set和映射Map。然后我们再使用链表和二叉树来初步实现Set和Map的功能,并研究下相关操作的时间复杂度。
OK,正餐开始(我是来对比树和链表的,别搞错)!
说起集合Set,其里面的元素不会重复,所以,经常使用集合来做去重操作。而日常工作中,典型的应用有:客户统计、文本词汇量统计等。
首先我们使用之前的链表来实现集合Set。
void add(E)
void remove(E)
boolean contains(E)
int getSize()
boolean isEmpty()
话不多少,直接上代码:
![022b3e8a11f97d3dfc717a5706d8ed8c.png](https://i-blog.csdnimg.cn/blog_migrate/80de569f19fd3704e5ad22ef37132b5d.jpeg)
链表LinkedList实现集合Set
接下来我们基于昨天的二分搜索树,来实现Set的功能。具体如下:
![8755d03e92ef38df2bf45ac360975b0e.png](https://i-blog.csdnimg.cn/blog_migrate/100c2deb7d1b9aa9574cbb13d9b0386e.jpeg)
BST实现集合Set
接下来我们分析下二者在时间复杂度上的区别。
首先对于链表来说,其添加元素add时,需要判断是否包含contains,所以其时间复杂度为O(n),删除操作也为O(n)。
那么对于二分搜索树来说,假如h为二分搜索树的高度,无论添加、删除、查找操作,时间复杂度都为O(h)。
接下来我们就研究下高度h和节点数n的关系,对于二分搜索树来说,其h层的元素个数最多为2^(h-1)个,那么一个h层的满二叉树其元素个数即为:
n = 2^0+2^1+2^2+...+2^(h-1)=2^h-1,用对数来表示就是:h=log(n+1)。那么用大O表示法就是O(h)=O(logn)。
对于二叉树来说,其最坏的情况就是退化为链表的形式,其最坏时间复杂度为O(n)。小伙伴们有兴趣的话,可以计算下,当n逐渐变大时,O(logn)和O(n)的区别。
当然,我写了个小脚本,来测验二者的区别:
![ce268181ef243f3e17d1a433359fe3c8.png](https://i-blog.csdnimg.cn/blog_migrate/4103e12a9a9651258a03aacd3e99023e.jpeg)
测试脚本
计算结果如下:
![45a2209f69c1242dcc41ad43885ef9ad.png](https://i-blog.csdnimg.cn/blog_migrate/573aa4561e2b97694dbf44926ca7fe63.jpeg)
BST Set 和Linked List Set区别
由此可以看出,用二叉树的效率比链表要快很多很多。同时,当时间复杂度涉及到log时,基本都是与树有关。
现在我们来看看映射Map,对于Map来说,它是一种存储(键, 值)数据对的数据结构(key, value)。比如x=f(n)这样的映射关系。日常使用中,我们会根据键(key),来快速查询值(value)。
同样,我们先用链表来实现映射Map,具体功能如下:
void add(k, v)
V remove(k)
boolean contains(k)
V get(k)
void set(k)
int getSize()
boolean isEmpty()
限于篇幅,我就把重要的功能实现代码展示一波:
![1cb18afb3c7da798f3fc782525a1d564.png](https://i-blog.csdnimg.cn/blog_migrate/e23b02af65e868c5bcd92f01bfe40f31.jpeg)
链表LinkedList实现映射Map 一
![d201e3a44f2b280a4e6e73ae6fad83e0.png](https://i-blog.csdnimg.cn/blog_migrate/ebbec365f6b27bf0c1d47c7bd2f0bc1c.jpeg)
链表LinkedList实现映射Map 二
整体基于链表来实现,设定虚拟头结点dummyHead,也算是又复习了一波链表。
下面来看基于二分搜索树实现的Map。
![2f3d12bbbea7c482ceb176a7261e5e61.png](https://i-blog.csdnimg.cn/blog_migrate/f370dad36d3b2069462e71800e9dc1ab.jpeg)
BST实现映射Map 添加操作
![882c787fe0029c83b45f42415a0e8879.png](https://i-blog.csdnimg.cn/blog_migrate/07537eb5fc5f6587645ac1472caa51bb.jpeg)
BST实现映射Map 删除操作
![5fa6f3a384ca54f6fb7830828e8e7033.png](https://i-blog.csdnimg.cn/blog_migrate/a7f8964813fe6451470c188b51a9b5ab.jpeg)
BST实现映射 查询操作
基本套用二分搜索树的逻辑,只是现在每个节点放的是(key, value)形式的数据,然后我们比较key值的大小,来实现左右子树的相关逻辑。
同样,我们最后来对比二者的时间复杂度,基于对链表的熟悉,我们知道无论是添加add、删除remove、修改set、查询contains等操作,其时间复杂度均为O(n)。而根据上述对于树结构的时间复杂度来看,其相关操作均为O(logn)。
OK,今天关于集合Set和映射Map的总结到这里,其实呢,主要是对比了链表和二叉树的时间复杂度……
那么,涉及到时间复杂度包含log的,基本都使用到树结构。另外,对于Set和Map,更多的东西,后续我会更新哈希表相关的知识点。
好了,今天就到这里。
拜了个拜~
![d2440bbba3b768b9bec77f6ab2c83d56.png](https://i-blog.csdnimg.cn/blog_migrate/b900c1183c50f4d3698c077d4be95bfc.jpeg)