快速理解红黑树原理

快速理解红黑树原理

红黑树 简介

红黑树 其实就是一个二叉树。


    1.0 常用的二叉树类型

    简单说二叉树概念:
    二叉树 又称度为至多二的树。

    1.1 平衡二叉树

    平衡二叉树又称 AVL 树
    特点:一个根节点的左右个子树的高度差不超过1

    平衡二叉树

    这里写图片描述

    非平衡二叉树

    这里写图片描述
    高度差已经大于1 了。
    平衡树解决的问题就是 能够最大限度的增加访问的每个节点的的平均性
    。保证每个节点被访问的次数平衡。



    1.2 完全二叉树

    除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。
    这里写图片描述
    堆排序 结构其实就是一个完全二叉树的结构,倒序和正序就是用的 大根堆 小根堆的原理。


    1.3 满二叉树

    每个节点是叶节点或者度为2.
    这里写图片描述


    1.4 查找二叉树

    这种树的特点是 每个根节点大于左子树上的任意一个节点,小于等于右子树上的任意一个节点。
    这里写图片描述
    举个简单例子:
    比如说 我现在要查找 4 这个数字 ,首先 我先比较 根节点就行,如果比根节点小的话,那么肯定在左边的子树列表里面。那么右边的就不用看了。然后依次同理比较。
    查找二叉树 能够提高查询速度的效率。

    但是还有一种情况 比较特殊:
    这里写图片描述
    这样的 比较尴尬了,一边倒的情况它也满足查找二叉树的概念。但是效率就不那么高效了。

    在说原理之前说一下
    高度与深度区别:

    • 深度定义是从上往下的
    • 高度定义是从下往上的
    • 空数高度0
    • 叶子结点高度1

    在这里插入图片描述
    在这里插入图片描述
    目前很多网上说法不一致 ,大概如上图两种情况 这紫色,橙色代表层数
    一般情况 根节点 根节点 是从0 或者 1

    此时树的深度为 3 高度 为 9–4–2–1 =4
    针对一颗树来说

    •  根结点0紫色,层数=深度=高度-1
       根结点1橙色,层数=深度=高度
      

    但是针对每一个树上的节点而言

    •  相同深度的每个结点,高度不一定相同,因为每个结点下面的叶结点的深度是不一定相同的
      

    如图:②④⑤ 他们高度 3 2 1 深度 1 2 2

    2.0 红黑树原理

    2.1 红黑树结构核心法则

    1. 每个节点要么是红色,要么是黑色
    2. 根节点【NULL】必须是黑色
    3. 节点是红色不能连续(如果节点是红色 ,孩子必须是黑色
    4. 从任意节点出发到其NULL节点 的简单路径上都包含相同数目的黑色节点★★★ (关键)
    5. 每个红色节点的两个子节点一定都是黑色(叶子节点包含NULL)

    2.2 红黑树的结构

    如图
    这里写图片描述
    红黑树从根节点到每个叶子节点的路径都包含相同数量的黑色节点,因此从根节点到叶子节点的路径中包含的黑色节点数被称为树的“黑色高度(black-height)

    一颗树黑色高度为3得红黑树,从根结点到叶结点的最短路径长度是3(黑-黑-黑),最长路径为4(黑-红-黑-红-黑)。由于第4条性质,不可能在最长路径中加入更多的黑色结点,因为性质3规定红色结点的子结点必须是黑色的,因此在同一简单路径中不允许有两个连续的红色结点。红黑树中最长路径就是一条红黑交替的路径
    对于给定的黑色高度为n的红黑树,从根结点到叶结点的简单路径的最短长度为n-1,最大长度为2(n-1)。所有对树的操作必须保持上面列出的属性。特别要指出的是,插入和删除树的结点的操作必须遵循这些原则。

    2.3 红黑树插入流程

    2.3.1 核心策略

    • 插入节点且将颜色染成红色
    • 重新染色 且基于 《红黑树核心法则2.1》 旋转 修复
    2.3.1.1 为什么要将节点染成 红色?

    插入的节点染成红色 会破坏 2 、3 法则,便于后续修复
    在这里插入图片描述

    2.3.2 插入常见几种情况

    在这里插入图片描述

    1. 红黑树结构不会旋转变化情况:
      1)当插入的节点为的父亲为黑色节点。【什么都不用做】
      2)被插入的节点是根节点。【直接把此节点涂为黑色】
    2. 红黑树结构发生旋转变化情况:
      1) 当前节点的父节点【60】是红色,且当前节点的祖父节点【40】的另一个子节点(叔叔节点)也是红色。
      2)当前插入的父节点是红色,当前叔叔节点的黑色,且当前节点为其父亲节点的左孩子。(进行左旋)
      3)当前插入的父节点是红色,当前叔叔节点的黑色,且当前节点为其父亲节点的右孩子。(进行右旋)

    如图 所示
    图片后续更新一版【】

    红黑树结构发生旋转变化情况已经对应的措施如下
    这里写图片描述

    左旋 : 右边过于臃肿
    右旋 : 左边过于臃肿
    相对复杂的红黑树 旋转最大不超过3次
    下面展示一个红黑树插入数据过程
    在这里插入图片描述

    树的旋转问题

    1.为什么会出现旋转?
    对于平衡树来说,当插入或者删除的时候,树的结构会发生破坏因此会导致。因此需要对树进行旋转来保证树的平衡。

    先拿 平衡二叉树的 查找二叉树举一个例子:
    这里写图片描述
    此时当前二叉树 是新增一个60数字红色。 此时 当前二叉树不平衡了,那么需要进行左旋 需要把当前40 那个节点作为跟节点,然后把30和20 旋转下来。
    这里写图片描述

    此时大家发现这样还是会有问题。发现又不满足二叉树了,现在变三叉了,不要急 ,此时再次挑战需要把中间的 33 那个分支砍掉,接在哪边呢?根据查找二叉树的规则,比根节点小的放在左边,比根节点大的放在右边。 33 比40 小 但是 比30 大。如图
    这里写图片描述

    红黑树应用

    TreeMap 典型红黑树
    Android Binder 虚拟内存 Intent IPC 1M 小内存块
    TreeMap

    左旋代码:

    //左旋右侧需要平衡
      private void rotateLeft(Entry<K,V> p) {
            if (p != null) {
             //拿到根节点的右子节点 
                Entry<K,V> r = p.right;
              //把根节点的右子节点的左节点,赋值
                p.right = r.left;
                if (r.left != null)
                //将根节点这个值赋值到当前断开的跟节点上
                    r.left.parent = p;
                //r 将来要成为新的根节点 p.parent 为根 ,使得他为新的跟节点 
                r.parent = p.parent;
                if (p.parent == null)
                    root = r;
                    //如果p 为左孩子,让他还是成为左孩子 同理
                else if (p.parent.left == p)
                    p.parent.left = r;
                else
                    p.parent.right = r;
                 //最后 将当前交换的跟换值
                r.left = p;
                p.parent = r;
            }
        }
    

    右旋代码:

     private void rotateRight(Entry<K,V> p) {
            if (p != null) {
                Entry<K,V> l = p.left;
                p.left = l.right;
                if (l.right != null) l.right.parent = p;
                l.parent = p.parent;
                if (p.parent == null)
                    root = l;
                else if (p.parent.right == p)
                    p.parent.right = l;
                else p.parent.left = l;
                l.right = p;
                p.parent = l;
            }
        }
    

    插入元素:

      public V put(K key, V value) {
            Entry<K,V> t = root;
            if (t == null) {
                compare(key, key); // type (and possibly null) check
    
                root = new Entry<>(key, value, null);
                size = 1;
                modCount++;
                return null;
            }
            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);
            }
            else {
                if (key == null)
                    throw new NullPointerException();
                @SuppressWarnings("unchecked")
                    Comparable<? super K> k = (Comparable<? super K>) key;
                do {
                    parent = t;
                    cmp = k.compareTo(t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            Entry<K,V> e = new Entry<>(key, value, parent);
            if (cmp < 0)
                parent.left = e;
            else
                parent.right = e;
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }
    

    红黑树相关定理

    1. 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。

      根据上面的性质5我们知道上图的红黑树每条路径上都是3个黑结点。因此最短路径长度为2(没有红结点的路径)。再根据性质4(两个红结点不能相连)和性质1,2(叶子和根必须是黑结点)。那么我们可以得出:一条具有3个黑结点的路径上最多只能有2个红结点(红黑间隔存在)。也就是说黑深度为2(根结点也是黑色)的红黑树最长路径为4,最短路径为2。从这一点我们可以看出红黑树是 大致平衡的。 (当然比平衡二叉树要差一些,AVL的平衡因子最多为1)

    2. 红黑树的树高(h)不大于两倍的红黑树的黑深度(bd),即h<=2bd

      根据定理1,我们不难说明这一点。bd是红黑树的最短路径长度。而可能的最长路径长度(树高的最大值)就是红黑相间的路径,等于2bd。因此h<=2bd。

    3**. 一棵拥有n个内部结点(不包括叶子结点)的红黑树的树高h<=2log(n+1)**

      下面我们首先证明一颗有n个内部结点的红黑树满足n>=2^bd-1。这可以用数学归纳法证明,施归纳于树高h。当h=0时,这相当于是一个叶结点,黑高度bd为0,而内部结点数量n为0,此时0>=2^0-1成立。假设树高h<=t时,n>=2^bd-1成立,我们记一颗树高 为t+1的红黑树的根结点的左子树的内部结点数量为nl,右子树的内部结点数量为nr,记这两颗子树的黑高度为bd'(注意这两颗子树的黑高度必然一 样),显然这两颗子树的树高<=t,于是有nl>=2^bd'-1以及nr>=2^bd'-1,将这两个不等式相加有nl+nr>=2^(bd'+1)-2,将该不等式左右加1,得到n>=2^(bd'+1)-1,很显然bd'+1>=bd,于是前面的不等式可以 变为n>=2^bd-1,这样就证明了一颗有n个内部结点的红黑树满足n>=2^bd-1。
    
        在根据定理2,h<=2bd。即n>=2^(h/2)-1,那么h<=2log(n+1)
    
        从这里我们能够看出,红黑树的查找长度最多不超过2log(n+1),因此其查找时间复杂度也是O(log N)级别的。
    

    红黑树的优势

    红黑树 优势
    红黑树能够以O(log2(N))的时间复杂度进行搜索、插入、删除操作。此外,任何不平衡都会在3次旋转之内解决。这一点是AVL所不具备的

    以上是本人学习红黑树的相关体会和心得。
    本文章学习相关内容是转载
    http://www.cnblogs.com/skywang12345/p/3245399.html
    https://www.cnblogs.com/gofighting/p/5437998.html
    https://blog.csdn.net/qq_36667170/article/details/84142019
    如果有兴趣的同学很可以去这个链接继续学习一下。

    红黑树是一种自平衡的二叉搜索树,它在插入和删除节点时通过一系列的操作来保持树的平衡。下面是红黑树的一些原理: 1. 节点颜色:每个节点被标记为红色或黑色。 2. 根节点和叶子节点:根节点是黑色的,叶子节点(空节点)是黑色的。 3. 节点关系:如果一个节点是红色的,则它的子节点必须是黑色的。 4. 黑色节点数量:从根节点到任意叶子节点的路径上,包括根节点和叶子节点,黑色节点数量相同。 5. 插入操作:插入新节点时,首先按照二叉搜索树的规则进行插入,然后根据红黑树的规则进行调整,使得树保持平衡。 - 如果插入节点的父节点是黑色的,那么不需要做任何操作。 - 如果插入节点的父节点是红色的,那么需要进行调整。 - 如果插入节点的叔叔节点也是红色的,将父节点和叔叔节点都设置为黑色,祖父节点设置为红色,并以祖父节点作为新插入节点进行进一步调整。 - 如果插入节点的叔叔节点是黑色的,需要进行旋转操作来保持平衡。根据具体情况,可以进行左旋、右旋或双旋操作。 6. 删除操作:删除节点时,首先按照二叉搜索树的规则进行删除,然后根据红黑树的规则进行调整,使得树保持平衡。 - 如果待删除节点有两个子节点,需要找到它的后继节点(比待删除节点大的最小节点)来替代待删除节点,然后再删除后继节点。 - 如果待删除节点有一个子节点或没有子节点,直接删除即可。 - 如果删除的节点是红色的,不会破坏红黑树的性质,不需要进行调整。 - 如果删除的节点是黑色的,需要进行调整来保持平衡。根据具体情况,可以进行旋转操作和改变颜色。 通过这些原理和调整操作,红黑树可以保持平衡,并且具有较好的查找、插入和删除性能。它被广泛应用于各种数据结构算法中。
    评论 7
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值