透过根源从而探究红黑树的本质,究竟二叉树是什么神仙鬼怪?
1. 查看根节点 41 2. 因为 41> 29 ,所以查看 41 的左孩子 20 3. 因为 20 < 29 ,所以查看 20 的右孩子 29,发现其正好是要查看的节点。 ![](https://static001.geekbang.org/infoq/a1/a10a9b4bef482b23403bd55637904482.gif) ### 退化 二叉查找树有个非常严重的问题,如果数据的插入是从大到小插入的,或者是从小到大插入的话,会导致二叉查找树退化成单链表的形式,俗称“瘸子“。 1. 左瘸子:例如,插入数据依次为{5,4,3,2,1}(从大到小),则如下图所示:![](https://static001.geekbang.org/infoq/78/78a594600a41334bc3d87dbfd5dbf12f.gif) 2. 右瘸子:例如,插入数据依次为{1,2,3,4,5}(从小到大),则如下图所示: ![](https://static001.geekbang.org/infoq/ec/eccddcdbe960145c4e725db05a2a0e0c.gif) 为了解决该问题,出现了一些解决方法,即平衡,能够使得树趋向平衡,这种自平衡的树叫做平衡树。 ## 平衡树 平衡树(Balance Tree,BT) 指的是,**任意节点的子树的高度差都小于等于 1**。常见的符合平衡树的有 AVL 树(二叉平衡搜索树),B 树(多路平衡搜索树,2-3 树,2-3-4 树中的一种),红黑树等。 ## AVL 树 AVL 树(由发明者**A**delson-**V**elsky 和?**L**andis 的首字母缩写命名),是**指任意节点的两个子树的高度差不超过 1 的平衡树**。又称 **自平衡二叉搜索树**。 AVL 树能解决上文二叉查找树中的右瘸子问题,例如,插入数据依次为{1,2,3,4,5}(从小到大),则如下图所示: **AVL 树会对不符合高度差的结构进行调整,从而使得二叉树趋向平衡**。 ![](https://static001.geekbang.org/infoq/41/41b2c8284221771eada19a503e56caed.gif) ## 2-3 树 ### 基本概念 **2-3 树**,是指每个具有子节点的节点(内部节点,internal node)要么有两个子节点和一个数据元素,要么有三个子节点和两个数据元素的自平衡的树,它的所有叶子节点都具有相同的高度。 简单点讲,2-3 树的非叶子节点都具有两个分叉或者三个分叉,所以,称作**2 叉-3 叉树**更容易理解。 另外一种说法,**具有两个子节点和一个数据元素的节点又称作 2 节点**,**具有三个子节点和两个数据元素的节点又称作 3 节点**,所以,整颗树叫做 2-3 树。 **所有叶子点都在树的同一层,一样高**。 > 性质 1\. 满足二叉搜索树的性质 > 性质 2\. 节点可以存放一个或两个元素 > 性质 3\. 每个节点有两个或三个子节点 ![](https://static001.geekbang.org/infoq/3b/3bb2b63157c8c2f3375e397894e61632.png) ### 创建 2-3 树的规则 插入操作 1. 向 2-节点中插入元素 ![](https://static001.geekbang.org/infoq/92/9232bc91d754cbdf52d7569108d0fc99.jpeg) 2. 向一颗只含有一个 3-节点的树中插入元素 ![](https://static001.geekbang.org/infoq/5c/5ca51c62df1dc51d067a314e055fa154.jpeg) ## 2-3-4 树 ### 含义 1. 2 节点:包含两个子节点和一个数据元素 2. 3 节点:包含三个子节点和一个数据元素 3. 4 节点:包含四个子节点和一个数据元素 **2-3-4 树**,它的每个非叶子节点,要么是 2 节点,要么是 3 节点,要么是 4 节点,且可以自平衡,所以称作 2-3-4 树。 ![](https://static001.geekbang.org/infoq/36/36a72bac2d044afc79f28b14abe95f1f.png) ### 规则 > 规则 1\. 加入新节点时,不会往空的位置添加节点,而是添加到最后一个叶子节点上 > 规则 2\. 四节点可以被分解三个 2-节点组成的树,并且分解后新树的根节点需要向上和父节点融合 ### 插入操作 1. 原本的 2-3-4 树 ![](https://static001.geekbang.org/infoq/36/36a72bac2d044afc79f28b14abe95f1f.png) 2. 对于上图的 2-3-4 树,插入一个节点 17,由于规则 1,节点 17 不会加入节点[16,18,20]的子树,而是与该节点融合。 ![](https://static001.geekbang.org/infoq/33/33e83a309f3f607a04169f5b95b50002.png) 3. 由于规则 2,节点[16,17,18,20]是一个 4 节点,将该节点进行拆解成新的树,将 18 作为子树的根节点进行拆分。 ![](https://static001.geekbang.org/infoq/16/1624050ad6f9a78a632a0bc423fff7b9.png) 4. 此时树暂时失去了平衡,我们需要将拆分后的子树的根节点向上进行融合。 ![](https://static001.geekbang.org/infoq/79/791d604828e95d4f2c5c030ca9f903ab.png) 5. 同理可得,由于规则 2,节点[6,10,14,18]是一个 4 节点,将该节点进行拆解成新的树,将 14 作为子树的根节点进行拆分,完成了 2-3-4 树的构建。 ![](https://static001.geekbang.org/infoq/10/105abeec0c0621b52d5a46242c69ed21.png) 总结了下插入节点的过程,无非也就为了符合两条规则,那么,2-3 树,2-3-4 树都有了,那是不是也有 2-3-4-5 树,2-3-4-5--...-n 树的存在呢?事实上是有的,世人把这一类树称为一个名字:B 树。 ## B 树 **B 树**,表示的是一类树,它允许一个节点可以有多于两个子节点,同时,也是自平衡的,叶子节点的高度都是相同的。 所以,为了更好地区分一颗 B 树到底属于哪一类树,我们给它一个新的属性:**度(Degree):一个节点能有多少箭头指向其他节点**。 具有度为 3 的 B 树,表示一个节点最多有三个子节点,也就是 2-3 树的定义。 具有度为 4 的 B 树,表示一个节点最多有四个子节点,也就是 2-3-4 树的定义。 度为 4 的 B 树的示例图: ![](https://static001.geekbang.org/infoq/36/36a72bac2d044afc79f28b14abe95f1f.png) ## 红黑树 ![](https://static001.geekbang.org/infoq/02/02c2e8cc92a715a3b56affc9edb7f621.png) ### 简介 R-B Tree,全称是 Red-Black Tree,又称为“**红黑树**”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。 ### 如何理解红黑树 一个经典的红黑树如下图所示(省略了叶子节点都是黑色的 NIL 节点) ![](https://static001.geekbang.org/infoq/92/921452362e5a2b86b33276ecf2db1aa5.png) 如图 2 所示,将该红黑树与上文讲到的 2-3-4 树对比,是否发现,**红黑树就是一个 2-3-4 树**。 ![](https://static001.geekbang.org/infoq/f5/f51ea699d049a1c17311aae3880ec0cd.png) 1. 每个节点或者是黑色,或者是红色。 2. **根节点是黑色**。 3. **每个叶子节点(NIL)是黑色**。[注意:这里叶子节点,是指为空(NIL 或 NULL)的叶子节点!] 4. 如果一个节点是红色的,则它的子节点必须是黑色的。 由于红黑树的每个节点都是由 2-3-4 树转化而来的,从而红色节点不能连续两个出现,不然会出现 4 节点的情况,导致违反了规则 2。而且红黑树的每一个黑节点都是 3 节点中的最中间的那个值,或者是 2 节点中其中一个值。 5. **从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点**。 原因:红黑树这些黑色节点在 2-3-4 树中代表的是由 1 节点的一个 2-3-4 树,而 2-3-4 树是同一个子树的深度是相同的,平衡的,所以从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。(如下图所示,蓝色代表是黑色节 ``` 【一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】 浏览器打开:qq.cn.hn/FTf 免费领取 ``` 点) ![](https://static001.geekbang.org/infoq/5f/5f7b9fc12ea4fb8f3e99837a2260c69c.png) 注意: 1. 特性(3)中的叶子节点,是只为空(NIL 或 null)的节点。 2. 特性(5),**确保没有一条路径会比其他路径长出俩倍**。因而,红黑树是相对是接近平衡的二叉树。 3. 红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为**O(log n)**。 > 由上面的例子所示,我们只要把红黑树当做是 2-3-4 树来处理,并且对应的颜色进行改变或者进行左旋右旋的操作,即可达到使得红黑树平衡的目标。 ### 如何保持红黑树的结构 当我们插入一个新的节点的时候,如何保证红黑树的结构依然能够符合上面的五个特性呢? 树的旋转分为左旋和右旋,下面借助图来介绍一下左旋和右旋这两种操作。 #### 左旋 ##### 原本的状态
评论