Java集合-TreeMap和红黑树

TreeMap是一种通过实现了红黑树数据结构的Map集合。

【图片有英文注释的均摘抄于国外文章】

首先,先来看一些基础概念。

1. 二叉排序树

二叉排序树的定义和性质:
(1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
【摘自百度百科】
.
如下图是一个普通的二叉树结构:

二叉树【摘抄于国外文章】

上图是相应的根据值比较生成的一个简单的二叉树,那么对应查找就非常简单,不断通过比较节点的值,大于就向右子树走,小于就往左子树走,相同则返回当前值.

二叉树查找【摘抄于国外文章】

对应插入就可以类似查找,先查到当前值于节点比较,如果找到,直接更新,没有找到就不断往子节点寻找,直到到达为空的子节点,将值填入到该空节点上。


二叉树插入【摘抄于国外文章】

二叉树查找的时候,查找的效率和树的形状有关,当节点完全平衡时(最底层子节点到根节点的“路程”相同),效率最高;当所有节点都只有一个子节点时,效率最差

二叉树效率【摘抄于国外文章】

2. B树

B-树是一种多路搜索树(并不一定是二叉的)
如下图,节点内有多个值(多路):


B树【摘抄于国外文章】

上图展示的最多只有两个三个子节点的B树,这种简单结构的树可以称为2-3树,这里点到为止,后续将通过这种树去分析后续的红黑树

3. 2-3树

2-3树允许每个节点保存1个或2个值,含有1个值节点称为2-node(有两个子节点),含有2个值的节点称为3-node(有三个子节点)。
如图:


2-3树【摘抄于国外文章】

在2-3树中查找,与二叉树类似,通过不断和节点比较进行向下查找,需要注意的是,在3-node节点中,需要同时比较两个值,如果介于两个值之间,需要找的子节点就是中间的子节点。

2-3树查找过程【摘抄于国外文章】

这里重点讨论一下插入操作,首先看一种简单的,往2-node节点插入;如果找到的末节点是一个2-node的节点,直接在此节点上新增当前值,将其节点变成3-node节点,如图:


2-3树2-node新增【摘抄于国外文章】

当插入的节点是3-node节点时,应该怎么操作?首先看一下一个最简单的,只有一个3-node节点的树:


2-3树3-node根新增【摘抄于国外文章】

首先,将值插入到当前的3-node节点,将其变成4-node节点,然后提取中间的值,让其分解为一个普通的二叉树即可。

那么如果当前插入的3-node节点有父节点时应该怎么处理呢,首先还是将3-node变成4-node节点,然后拆解出一个父节点插入到原来的父节点中,如果当前父节点是2-node节点,那么将其变成3-node节点,如果原来父节点已经是3-node节点,那么循环上面的处理步骤。

2-3树3-node根新增【摘抄于国外文章】
2-3树3-node根新增【摘抄于国外文章】

总结一下步骤:

  1. 查找需要插入值的位置
  2. 判断当前插入节点是否是2-node节点,如果是,则将其变成3-node节点,如不是,继续执行一下步骤
  3. 将当前节点变成4-node节点
    4.分解当前4-node节点,判断当前节点是否为根节点,如果是,将整个2-3树,提高一层,如不是,继续执行一下步骤
  4. 新增的上层节点插入到父节点中,重复执行2-4步,直到结束

4. 红黑树

红黑树是一种解决平衡二叉树的方法。红黑树具有以下性质:

  1. 节点是红色或黑色。
  2. 根节点是黑色。
  3. 每个叶节点(NIL节点,空节点)是黑色的。
  4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
    5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
    【摘自百度百科】
红黑树【摘抄于国外文章】

红黑树其实是2-3树的一种二叉树表现方法,如果将红线连接线水平连接,那么连接的两个节点就是2-3树中的3-node节点,其他没有红线连接的就是2-3树中的2-node节点,如图:

红黑树与2-3树【摘抄于国外文章】

在讲解插入操作前,先了解集中红黑树的平衡操作。第一种是左旋转和右旋转:

左旋转【摘抄于国外文章】
右旋转【摘抄于国外文章】

第二种是颜色反转,当出现一个节点下的两个节点均是红色时,可以转换到2-3树中思考,这是一个4-node节点,那么需要将其分解为一个二叉树,并向上合并:

颜色转换【摘抄于国外文章】

有了2-3树的插入讲解,这边,直接分析最复杂的红黑树插入:

红黑树插入【摘抄于国外文章】
  1. 查找需要插入值的位置
  2. 新插入的节点元素用红色标识(2-3树中插入到2-node节点,将其变成3-node节点)
  3. 如果出现节点下的两个子节点都是红色时(4-node节点),需要进行颜色转换(或旋转)

选取红黑树比完全平衡二叉树的好处就是,红黑树是一种代价较小就可以实现较平衡的二叉树的结构,最差的情况也就是比完全二叉树的深度多一倍,但是在删除操作的平衡里面可以节省很多的效率。

5. TreeMap

通过分析二叉树和红黑树的概念,再来看源码,首先看TreeMap的容器:

private transient Entry<K,V> root = null;

其中,TreeMap重写了Entry类:

K key;
V value;
Entry<K,V> left = null;
Entry<K,V> right = null;
Entry<K,V> parent;

其中key value是为了实现Map的键值结构,left、right、parent表示的是二叉树中一个节点与其他节点的关系指针。

TreeMap提供了节点值比较的接口:

private final Comparator<? super K> comparator;

接下来,看一下put方法:

public V put(K key, V value) {
    Entry<K,V> t = root;
    ... ...
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    ... ...
    fixAfterInsertion(e);
    ... ...
}

首先获取当前的比较器,运用当前比较器作为后续比较的工具(比较器为空则用默认的,默认的逻辑和有比较器的类似,不重复分析).然后小于,则跳到左边的节点继续比较,如果大于则在右边子节点比较,如果相同,则设置当前值。然后调用fixAfterInsertion平衡红黑树操作。

先偷一下懒,里面的平衡源码就不分析了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容