TreeMap简析

来源:互联网 发布:王者荣耀淘宝充值 编辑:程序博客网 时间:2024/06/11 00:50

红黑树的演化

既然叫TreeMap,那么肯定是建立在树这种数据结构的Map了,是什么数呢?叫红黑树。
说到红黑树,就不得不说二叉查找树。二叉查找树是每个节点大于其左子节点而小于其右子节点的二叉树。如果只是满足定义,那么下图所示都满足条件:
这里写图片描述
但是左图退化成链表的存在,肯定不是我们所需要的,那么既然这样,肯定需要有种算法,来保证树不会退化,保证查找的速度。
理想中的情况应该是上图右所示的二叉树,二分法查找logN时间复杂度,最快的速度。但是如何进行维护这么一颗树,也就是如何平衡,因为每次插入,删除都有可能打破现有的平衡,那么就需要重新平衡,而维护完全的平衡二叉查找树,却太过复杂。
为了在维持平衡和查询速度进行折中,AVL树诞生,它要求在任何节点的两个子树的高度最大差别为1,AVL树通过一些列的旋转操作使树保持平衡,由于它的要求还是比较严格,导致维持平衡的代价过大,从而没有成功真正使用的经典数据结构。
而红黑树确实非常适合,而它的实现思路是借助2-3树的,且2-3树建立树的过程相对简单,我们就以2-3树开始分析,
首先看先2-3树的特性,这是摘抄自百度文库的定义:
数据项放入2-3树节点中的规则是:
1. 2-节点有两个孩子,必含一个数据项,其查找关键字大于左孩子的查找关键字,而小于右孩子的查找关键字。
2. 3-节点有三个孩子 ,必含两个数据项,其查找关键字S和L满足下列关系:S大于左孩子的查找关键字,而小于中孩子的查找关键字;L大于中孩子的查找关键字,而小于右孩子的查找关键字。
何为2-节点,何为3-节点呢?看下图:
这里写图片描述
这就是一棵2-3树,所有的叶子节点都在同一层,这就是所谓的高度平衡。从图上可以看出,虽然不是严格的二叉树,但是从图上大概可以估算出查找的时间复杂度应该是很接近logN。
那2-3树是怎么维持平衡的呢?如何进行插入呢?简单说,先进行遍历,找到相同的就替换,没有相同的就找到最后的叶子节点,然后把新节点挂在树的底部。我们看下图是我用ACEJHLPRSXM顺依次构造的二叉树过程(删除的操作有兴趣可以自己研究),能够清楚的演示二叉树维持平衡的过程。2-3树会因为插入的顺序不同,而出现不同的结构。
这里写图片描述
那什么这和红黑树到底有什么关系了。由于2-3树节点的不统一,造成了编程的困难,为了应付这种情况,用标准的二叉树和一些额外的信息,来表示2-3树,这之一就是红黑树,用红链将2个2-节点连起来作为构成一个3-节点。
下图就是有2-3树变化到红黑树的结构(左边的是2-3树的结构),由图可以清楚的看出,其实就是一种演变,我们可以通过2-3树相同的步骤,来组件红黑树,具体的构造有兴趣的可以自己研究。
这里写图片描述
数据结构的分析就到此为止吧,毕竟本文的主要目的是 TreeMap。

TreeMap的讲解

TreeMap是建立在红黑树的基础上的,那么常用的操作有哪些呢?

方法 描述 V put(K key, V value) 插入操作 V get(Object key) get操作 V remove(Object key) 删除操作 Set< K > keySet() 键集合 Set< Map.Entry > entrySet() 值集合 Map.Entry firstEntry() 获取第一个节点(根或者最左) Map.Entry lastEntry() 获取最后一个节点(根或者最右)

突然觉得没什么要写的了,因为treeMap整个就是一颗红黑树,一颗平衡的查找树,按照key来进行排序,图都很清楚了,如果在把java源码贴出来,感觉有点凑字的感觉。entrySet和 keyset几乎一样的代码,都是遍历器的实现,一个个按照顺序取出。红黑树是颗平衡树,本身就是为了考虑有序和遍历速度的平衡而设计的,节点最坏的情况为:红黑相间的路径长度是全黑路径长度的2倍,所以,遍历还是非常快速,时间复杂度为logN。
其他的方法,好像不怎么常用,treemap本身好似就不常用。但是常用的一种数据结构好像非常类似treemap,redis的有序集合sortset,通过分数来排序,附带value,不过sortset并不是用的红黑树实现,而是跳表(Skip List),有兴趣可以自行研究。

0 0
原创粉丝点击