Java 基础篇--基础知识之集合TreeMap

TreeMap 简介

TreeMap是NavigableMap接口(SortedMap的子接口)的实现类,是一个有序的key-value集合,它是通过红黑树(Red-Black tree)实现的。TreeMap能够把它保存的记录根据key键排序,它有两种排序方式:

  • 自然排序(默认排序):TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException;
  • 定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现
    Comparable 接口。

注意:

  1. 判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0;
  2. TreeMap存储的键key不可为null。

一、红黑树简单回顾

1.1 红黑树规则特点

  • 节点分为红色或者黑色;
  • 根节点必为黑色;
  • 叶子节点都为黑色,且为null;
  • 连接红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点);
  • 从任意节点出发,到其每个叶子节点的路径中包含相同数量的黑色节点;
  • 新加入到红黑树的节点为红色节点;

1.2 红黑树自平衡基本操作

  • 变色:在不违反上述红黑树规则特点情况下,将红黑树某个node节点颜色由红变黑,或者由黑变红;
  • 左旋:逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点;左旋时机是父亲是红色,叔叔是黑色,当前是右子树,则直接以父亲为支点进行左旋;
    在这里插入图片描述
  • 右旋:顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点;右旋时机::父亲是红色,叔叔是黑色,当前是左子树,则把父亲变成黑色,爷爷变成红色,再以爷爷为支点进行右旋;
    在这里插入图片描述

二、实现原理

TreeMap底层是基于红黑树实现,具有红黑树的特点;在插入或删除树节点时,通过遍历树,找到对于位置,进行插入或删除。此时红黑树的平衡可能被破坏了。此时我们通过变色、左旋转和右旋转来进行树的平衡,从而使得整个树重新达到平衡并且满足红黑树的所有性质。

三、源码分析

3.1 继承与实现关系

在这里插入图片描述
在这里插入图片描述

  1. 继承于AbstractMap【 提供 Map 接口的骨干实现】,实现了NavigableMap,NavigableMap接口继承了SortedMap接口,可支持一系列的导航定位以及导航操作的方法,所以它是一个有序的Map;
  2. 实现了Cloneable接口,意味着它能被克隆;
  3. 实现了java.io.Serializable接口,意味着它支持序列化。

3.2 重要成员信息

在这里插入图片描述

  1. comparator:内部的比较器,若为空,则为自然顺序;
  2. root:红黑树唯一的根节点;
  3. size:红黑树中节点Entry的数量;
  4. modCount: 红黑树结构的调整次数

3.3 构造方法

在这里插入图片描述

  1. TreeMap():默认构造函数,按照key的自然顺序排列;
  2. TreeMap(Comparator<? super K> comparator):传递Comparator具体实现,按照该实现规则进行排序;
  3. TreeMap(Map<? extends K, ? extends V> m):传递一个map实体构建TreeMap,按照默认规则排序;
  4. TreeMap(SortedMap<K, ? extends V> m):传递一个map实体构建TreeMap,按照传递的map的排序规则进行排序。

3.4 数据结构

在这里插入图片描述
Entry静态内部类实现了Map的内部接口Entry,提供了红黑树存储结构的java实现,通过left属性可以建立左子树,通过right属性可以建立右子树,通过parent可以往上找到父节点。
在这里插入图片描述

3.5 重要方法

3.5.1 存储 put(K key, V value)

在这里插入图片描述
对于排序二叉树的创建,其添加节点的过程如下:

  1. 以根节点为初始节点进行检索。
  2. 与当前节点进行比对,若新增节点值较大,则以当前节点的右子节点作为新的当前节点。否则以当前节点的左子节点作为新的当前节点。
  3. 循环递归2步骤知道检索出合适的叶子节点为止。
  4. 将新增节点与3步骤中找到的节点进行比对,如果新增节点较大,则添加为右子节点;否则添加为左子节点。

put方法源码中通过 fixAfterInsertion(e) 方法来进行自平衡处理,我们回顾一下插入时自平衡调整的逻辑
在这里插入图片描述
在这里插入图片描述
左旋:
在这里插入图片描述
右旋:
在这里插入图片描述

3.5.2 读取 get(Object key)

在这里插入图片描述

3.5.3 移除 remove(Object key)

删除节点(P)的所有情况:

  1. p 是跟节点:直接删除P即可;
  2. P 无子节点:直接删除P节点,若P是红色,则不会影响树的结构,若P是黑色,则进行平衡调整;
  3. P 有一个子节点:则使用其子节点来替代P,并删除P,若P是黑色,则进行平衡调整;
  4. P 有两个子节点:需要找一个一个替代节点(规则:右分支最左边,或者左分支最右边的节点),使用替代节点来替代P,并删除P,若P是黑色,则进行平衡调整;
    • 4.1 P的兄弟节点Q为红色:进行”改变W. P的颜色,然后进行一次左旋转“处理,处理后转变为下面2、3、4三种情况;
    • 4.2 P的兄弟Q是黑色的,且w的俩个孩子都是黑色的:进行”将Q置为红色“处理,,处理后转变为下面3、4两种情况;
    • 4.3 P的兄弟Q是黑色的,w的左孩子是红色,w的右孩子是黑色:进行”将兄弟节点与其左子树进行颜色互换然后进行右转“处理,处理后转变为下面4这种情况;
    • 4.4 P的兄弟Q是黑色的,且w的右孩子时红色的:进行”交换兄弟节点和父节点的颜色,同时将兄弟节点右子树设置为黑色,最后左旋转“处理。

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值