Map数据结构及其底层简单实现
其实Java中的map就是映射,叫字典也可以,其实map也是一种容器,在这里为了深入的去理解map这种数据结构,从底层自己简单的实现 一下。
使用链表作为底层基础来实现Map
其实链表这种数据结构我们知道其一般只包含next和value两个属性,但是其实你也可以多给他添加一个key的属性。这样的话就和我们的map这种数据结构很像了,具体的实现如下:
1 | public class LinkedListMap <K,V> implements Map<K,V> { |
使用二分搜索树的思想来实现
其实二分搜索树和用链表的思想来实现map的道理是一样的,每个树节点除了原来的value,左孩子和右孩子,你再添加一个key的属性就可以了,具体的实现如下:
1 | public class BSTMap<K extends Comparable<K>, V> implements Map<K, V> { |
复杂度分析
使用二分搜索树和使用链表来实现map他的时间复杂度是不同的,因为这两种数据结构是不一样的,对于不同具体的是怎样的?如下表:
LinkListMap | BSTMap | BSTMap | BSTMap | |
---|---|---|---|---|
严格讲(h树的深度) | 平均 | 最差 | ||
增add | O(n) | O(h) | O(logn) | O(n) |
删remove | O(n) | O(h) | O(logn) | O(n) |
改set | O(n) | O(h) | O(logn) | O(n) |
查get | O(n) | O(h) | O(logn) | O(n) |
查contains | O(n) | O(h) | O(logn) | O(n) |
其实对于正常情况下,链表因为一般从头到尾需要遍历一遍,一般对应的操作的时间复杂度是O(n)的;
对于二分搜索树,其实操作一般是二分查找,时间复杂度是和树的深度是相关的,所以是O(logn)的,但是也不排除特殊情况,当一棵树退化成链表的时候如下:这时候他的时间复杂度也就和链表是一样的了。
应用
在LeetCode上有这么一道题目
1 | Given two arrays, write a function to compute their intersection. |
这里使用map这种数据结构去来处理这个问题,其实就是把一个数组中的元素放入map中作为key,以为key是不可重复的,然后数组中有重复元素怎么办?就value这个属性存放元素的个数。然后不断地查询另一个数组中的元素在map中的数量,找到一个就存一个,然后map中该元素对应的数量就减一个,具体的实现就如下:
1 | public class MapSolution { |