数据结构--红黑树

2-3树
2-3树
  • 满足二分搜索树的基本性质
  • 节点可以存放一个元素或者两个元素
  • 每个节点可以有2个孩子(二节点) 或者3个孩子(三节点)
  • 绝对平衡的树(从根节点到任意一个叶子节点所通过的节点数量一定是相同的)
2-3树保持平衡

添加节点永远不会去空的节点,会和最后找到的叶子节点做融合。

添加12
添加2
添加4
添加4

红黑树

等价于2-3树

  • 保持黑平衡的二叉树,左右子树的黑色节点的高度差保持绝对平衡,2-3树本身是保持绝对平衡的
  • 每个节点或者是红色的,后者是黑色的
  • 根节点是黑色的
  • 每一个叶子节点(最后的空节点)是黑色的
  • 如果一个节点是红色,它的孩子节点都是黑色,黑色节点的右孩子一定是黑色的
  • 从任意一个节点出发到叶子节点,经过的黑色节点是一样的
  • 所有的红色节点向左倾斜
  • 最大高度:2logn
红黑树与2-3树
//红黑树基于二分搜索树
public class RedBlackTree <K extends Comparable<K>, V>{

    private static final boolean RED = true;
    private static final boolean Black = false;

    private class Node{
        public K key;
        public V value;
        public Node left, right;
        public boolean color;

        public Node(K key, V value){
            this.key = key;
            this.value = value;
            left = null;
            right = null;
            color = RED;//因为在2-3树中添加的节点永远都是要融合到已有的节点中
        }
    }

    private Node root;
    private int size;

    public RedBlackTree(){
        root = null;
        size = 0;
    }

    public int getSize() {
        return size;
    }


    public boolean isEmpty() {
        return size == 0;
    }


    //判断node颜色
    private boolean isRed(Node node) {
        if (node == null)
            return Black;
        return node.color;
    }

    public boolean contains(K key) {
        return getNode(root, key) != null;
    }


    public V get(K key) {
        Node node = getNode(root, key);
        return node == null? null : node.value;
    }


    public void set(K key, V newValue) {
        Node node = getNode(root, key);
        if (node == null)
            throw new IllegalArgumentException(key + "doesn`t exist");
        node.value = newValue;
    }

}
添加元素相关操作
  • 左旋转,当添加的元素大于节点时,进行左旋转。(红色节点需要向左倾斜)
添加42

左旋转

左旋转代码

    //     node                                x
    //    /   \           左旋转             /    \
    //   T1    x      ----------->       node    T3
    //       /  \                       /   \
    //      T2  T3                     T1   T2
    //左旋转
    private Node leftRotate(Node node) {

        Node x = node.right;
        //左旋转
        node.right = x.left;
        x.left = node;

        x.color = node.color;
        node.color = RED; //是2-3树中的三节点

        return x;
    }
  • 颜色翻转,添加66,因为42需要继续向上融合(向红黑树中的3节点添加元素)
添加66
颜色翻转

颜色翻转代码

    private void flipColors(Node node) {
        node.color = RED; //由于需要继续向上融合 所以是红色 
        node.left.color = Black;  // 三个二节点 是黑色
        node.right.color = Black; // 三个二节点 是黑色
    }
  • 右旋转,需要翻转颜色
添加12
右旋转
颜色翻转

右旋转代码

    //右旋转
    //        node                           x
    //        /   \       右旋转            /   \
    //       x    T2  -------------->     y    node
    //     /  \                               /   \
    //    y   T1                             T1   T2
    private Node rightRotate(Node node) {
        Node x = node.left;

        //右旋转
        node.left = x.right;
        x.right = node;

        x.color = node.color;
        node.color = RED;

        return x;
    }
  • 先左旋转在右旋转在翻转颜色


    添加中间值元素
先左旋转
再右旋转
颜色翻转
添加元素过程总结
添加元素维护逻辑
    //向红黑树中添加元素
    public void add(K key, V value) {
        root = add(root, key, value);
        root.color = Black;  //最终的根节点为黑色节点
    }


    //以向node为根的红黑树中插入元素(key, value), 递归算法
    //返回插入新节点后红黑树的根
    private Node add(Node node, K key, V value) {
        if (node == null) {
            size ++;
            return new Node(key, value); // 默认插入红色节点
        }

        //如果相等 则不作处理
        if (key.compareTo(node.key) < 0)
            node.left = add(node.left, key, value);
        else if (key.compareTo(node.key) > 0)
            node.right = add(node.right, key, value);
        else // ==
            node.value = value;

        //右孩子是红色 左孩子不是红色的
        if (isRed(node.right) && !isRed(node.left))
            node = leftRotate(node);

        //左孩子 以及 左孩子的左孩子都是红色的
        if (isRed(node.left) && isRed(node.left.left))
            node = rightRotate(node);

        //左孩子 与 右孩子 都是红色的
        if (isRed(node.left) && isRed(node.right))
            flipColors(node);

        return node;
    }

性能总结

对于完全随机的数据,普通的二分搜索树很好用
缺点:极端情况下退化成链表(或者高度不平衡)
对于查询较多的使用情况,AVL树很好用
红黑树牺牲了平衡性(2logn的高度)
红黑树统计性能更优(综合增删改查所有的操作),平均性能优于AVL树。
数据结构中经常发生添加,删除的情况时,红黑树更合适。查询并不占优势。
如果数据近乎不会动的话,只查询,AVL树性能更好。

时间复杂度: O(logn)

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

推荐阅读更多精彩内容

  • 红黑树简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二分搜索树。红黑树...
    habit_learning阅读 686评论 0 1
  • 2-3树 在了解红黑树之前,我们先来认识2-3树,在算法(第4版)[https://book.douban.com...
    端碗吹水阅读 248评论 0 1
  • 什么是红黑树? 红黑树的定义 每个节点或者是红色的,或者是黑色的。 根节点是黑色的。 每一个叶子节点(最后的空节点...
    花逝97阅读 221评论 0 1
  • 接上章: B树(多路查找树) 本章主要介绍【红黑树】的性质以及【红黑树】节点的增加和删除操作。是类比B树节点的增加...
    翀鹰精灵阅读 441评论 0 2
  • 红黑树 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,典型的用途是实现关联数组。它是复杂的,...
    刘晖阅读 906评论 0 6