
熬夜写代码
关注公众号:EZ大数据。
每天学习一点点,不亏!
"
世界上最重要的事情是理解现实如何运行,一级如何应对现实。面对这一过程的心态至关重要!
——达利欧《原则》
"
昨天说完二叉搜索树,今天来个简单点的:集合Set和映射Map。然后我们再使用链表和二叉树来初步实现Set和Map的功能,并研究下相关操作的时间复杂度。
OK,正餐开始(我是来对比树和链表的,别搞错)!
说起集合Set,其里面的元素不会重复,所以,经常使用集合来做去重操作。而日常工作中,典型的应用有:客户统计、文本词汇量统计等。
首先我们使用之前的链表来实现集合Set。
void add(E)
void remove(E)
boolean contains(E)
int getSize()
boolean isEmpty()
话不多少,直接上代码:

链表LinkedList实现集合Set
接下来我们基于昨天的二分搜索树,来实现Set的功能。具体如下:

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)的区别。
当然,我写了个小脚本,来测验二者的区别:

测试脚本
计算结果如下:

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()
限于篇幅,我就把重要的功能实现代码展示一波:

链表LinkedList实现映射Map 一

链表LinkedList实现映射Map 二
整体基于链表来实现,设定虚拟头结点dummyHead,也算是又复习了一波链表。
下面来看基于二分搜索树实现的Map。

BST实现映射Map 添加操作

BST实现映射Map 删除操作

BST实现映射 查询操作
基本套用二分搜索树的逻辑,只是现在每个节点放的是(key, value)形式的数据,然后我们比较key值的大小,来实现左右子树的相关逻辑。
同样,我们最后来对比二者的时间复杂度,基于对链表的熟悉,我们知道无论是添加add、删除remove、修改set、查询contains等操作,其时间复杂度均为O(n)。而根据上述对于树结构的时间复杂度来看,其相关操作均为O(logn)。
OK,今天关于集合Set和映射Map的总结到这里,其实呢,主要是对比了链表和二叉树的时间复杂度……
那么,涉及到时间复杂度包含log的,基本都使用到树结构。另外,对于Set和Map,更多的东西,后续我会更新哈希表相关的知识点。
好了,今天就到这里。
拜了个拜~
