红黑树新解(删除)

4.1 元素删除

约定:

删除一个结点z,如果有该结点有子结点,需要查找该结点的左树最大值y来替换,同时又需要用叶结点x来替换y的位置。

在二叉树中删除一个结点有以下几种情况,以删除红结点为例,删除黑结点也差不多,最重要的多必须检查代替的结点是不是子结点,是不是黑结点。

Tip: 算法导论中谈到找右树最小值,我这里以左树最大值来代替删除结点,只是left和right的替换而已,原理都是一样。可以参照 红黑树可视化网站,https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 我也受益很多。

以后有空的时候再组织语言,感谢

附上代码方便参阅。

package alf.collection;

/**
 * Red -Black tree struct, make values‘ hash as key
 * @param <V>
 */
public class SimpleRBTree<V> {

    public SimpleRBTree() {
        leaf = new SimpleRBNode<>(Integer.MIN_VALUE, null, null);
        leaf.color = RBColor.BLACK;
        leaf.left = leaf.right = leaf;

        root = leaf;
    }

    public void Insert(V... values) {
        for (V item : values) {
            Insert(item);
        }
    }

    public void Insert(V value) {
        int key = value.hashCode();
        SimpleRBNode<V> node = new SimpleRBNode<V>(key, value, leaf);

        SimpleRBNode y = leaf;
        SimpleRBNode<V> x = root;
        while (x != leaf) {
            y = x;
            if (key < x.key)
                x = x.left;
            else if (key > x.key)
                x = x.right;
            else
                break;
        }
        if (root == y ) {
            if (root == leaf ) {
                root = node;
                root.color = RBColor.BLACK;
                return;
            }
            else if (root.key == key) {
                root.value = value;
                return;
            }
        }
        if(y.key == key)
        {
            y.value = value;
            return;
        }
        node = new SimpleRBNode<V>(key, value, leaf);
        node.parent = y;

        if (key < y.key) {
            y.left = node;
        } else if (key > y.key) {
            y.right = node;
        } else {
            node.parent = y.parent;
            node.left = y.left;
            node.right = y.right;
            if (y.parent != leaf) {
                if (y.parent.left == y)
                    y.parent.left = node;
                else if (y.parent.right == y)
                    y.parent.right = node;
            }
        }

        InsertFixUp(node);
    }

    /**
     * condition: both current node and parent node are RED
     * Case1: currentnode =grandpa node->left->left; make grandpa RED,mak parent node Black . RotateRight with parent node, z = z.parent.parent;
     * case2: currentnode =grandpa node->right->right; make grandpa RED,mak parent node Black . RotateLeft with parent node, z = z.parent.parent;
     * case3:parent and uncle node are RED, then set grandpa node RED; parent and uncle node BLACK.  z=z.parent
     * case4: currentnode =grandpa node->left->right; RotateLeft with parent node,goto case 1
     * case5: currentnode =grandpa node->right->left; RotateRight with parent node,goto case 2
     *
     * @param z
     */
    private void InsertFixUp(SimpleRBNode<V> z) {
        SimpleRBNode y = leaf;
        while (z.color == RBColor.RED && z.parent.color == RBColor.RED) {
            if (z.parent == z.parent.parent.left) {
                y = z.parent.parent.right;
                if (y != leaf && y.color == RBColor.RED) {
                    //case 3
                    z.parent.color = RBColor.BLACK;
                    y.color = RBColor.BLACK;
                    z.parent.parent.color = RBColor.RED;
                    z = z.parent.parent;
                } else if (z == z.parent.right) {
                    //case 5
//                    way1:
//                    z=z.parent;
//                    RotateLeft(z);
//                    z.parent.color = RBColor.BLACK;
//                    z.parent.parent.color = RBColor.RED;
//                    RotateRight(z.parent.parent);

                    //way2,  RotateLeft and goto case3
                    z = z.parent;
                    RotateLeft(z);
                } else {//left-left
                    //case 1
                    z.parent.color = RBColor.BLACK;
                    z.parent.parent.color = RBColor.RED;
                    RotateRight(z.parent.parent);
                    z = z.parent;
                }
            } else if (z.parent == z.parent.parent.right) {
                y = z.parent.parent.left;
                if (y != leaf && y.color == RBColor.RED) {
                    //case 3
                    z.parent.color = RBColor.BLACK;
                    y.color = RBColor.BLACK;
                    z.parent.parent.color = RBColor.RED;
                    z = z.parent.parent;
                } else if (z == z.parent.left) {
                    //case5

                    //way1:
//                    z=z.parent;
//                    RotateRight(z);
//                    z.parent.color = RBColor.BLACK;
//                    z.parent.parent.color = RBColor.RED;
//                    RotateLeft(z.parent.parent);

                    //way2:z=z.parent,Rotate current node  Right and goto case 2
                    z = z.parent;
                    RotateRight(z);
                } else {
                    //case 2
                    z.parent.color = RBColor.BLACK;
                    z.parent.parent.color = RBColor.RED;
                    RotateLeft(z.parent.parent);
                    z = z.parent;
                }
            }
        }

        root.color = RBColor.BLACK;
    }

    public SimpleRBNode<V> Get(int key) {
        SimpleRBNode x = root;
        boolean inFlag = false;
        while (x != leaf) {
            inFlag = true;
            if (key == x.key ) {
                break;
            } else if (key < x.key)
                x = x.left;
            else
                x = x.right;
        }
        return x;
    }

    public void Delete(V value) {
        SimpleRBNode x = Get(value.hashCode());

        if (x != leaf)
            Delete(x);

    }

    public void Delete(SimpleRBNode z) {
        SimpleRBNode x = leaf;
        SimpleRBNode y = z;
        RBColor y_original_Color = y.color;
        if (z.left == leaf) {
            x = z.right;
            RBTran(z, z.right);
        } else if (z.right == leaf) {
            x = z.left;
            RBTran(z, z.left);
        } else {
            y = TreeMax(z.left);
            y_original_Color = y.color;
            x = y.left;
            if (y.parent == z)
                x.parent = y;
            else {
                RBTran(y, y.left);
                y.left = z.left;
                y.left.parent = y;
            }
            RBTran(z, y);
            y.right = z.right;
            y.right.parent = y;
            y.color = z.color;
        }

        if (y_original_Color == RBColor.BLACK)
            DeleteFixUp(x);

        z.parent = leaf;
        z.left = leaf;
        z.right = leaf;
    }

    private void DeleteFixUp(SimpleRBNode x) {
        SimpleRBNode w = leaf;
        while (x != root && x.color == RBColor.BLACK) {
            if (x == x.parent.left) {
                w = x.parent.right;
                if (w.color == RBColor.RED) {
                    w.color = RBColor.BLACK;
                    x.parent.color = RBColor.RED;
                    RotateLeft(x.parent);
                    w = x.parent.right;
                    //System.out.printf("\nleft:case1\n");
                }
                if (w.left.color == RBColor.BLACK && w.right.color == RBColor.BLACK) {
                    w.color = RBColor.RED;
                    x = x.parent;
                    //System.out.printf("\nleft:case2\n");
                }
                else if (w.right.color == RBColor.BLACK) {
                    w.left.color = RBColor.BLACK;
                    w.color = RBColor.RED;
                    RotateRight(w);
                    w = x.parent.right;
                    System.out.printf("\nleft:case3\n");
                }
                else {
                    w.color = w.parent.color;
                    x.parent.color = RBColor.BLACK;
                    w.right.color = RBColor.BLACK;
                    RotateLeft(x.parent);
                    x = root;
                    //System.out.printf("\nleft:case4\n");
                }
            } else {//x==x.parent.right
                w = x.parent.left;
                if (w.color == RBColor.RED) {
                    w.color = RBColor.BLACK;
                    x.parent.color = RBColor.RED;
                    RotateRight((x.parent));
                    w = x.parent.left;
                    //System.out.printf("\nright:case1\n");
                }
                if (w.right.color == RBColor.BLACK && w.left.color == RBColor.BLACK) {
                    w.color = RBColor.RED;
                    x = x.parent;
                    //System.out.printf("\nright:case2\n");
                }
                else if (w.left.color == RBColor.BLACK) {
                    w.right.color = RBColor.BLACK;
                    w.color = RBColor.RED;
                    RotateLeft(w);
                    w = x.parent.left;
                    System.out.printf("\nright:case3\n");
                }
                else {
                    w.color = w.parent.color;
                    x.parent.color = RBColor.BLACK;
                    w.left.color = RBColor.BLACK;
                    RotateRight(x.parent);
                    x = root;
                    //System.out.printf("\nright:case4\n");
                }
            }
        }
        if (x.color != RBColor.BLACK) {//System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            x.color = RBColor.BLACK;
        }
        leaf.color = RBColor.BLACK;

    }

    private SimpleRBNode TreeMax(SimpleRBNode node) {
        SimpleRBNode x = node;
        SimpleRBNode y = leaf;
        while (x != leaf) {
            y = x;
            x = x.right;
        }
        if (y != leaf)
            return y;
        return node;
    }

    private SimpleRBNode TreeMin(SimpleRBNode node) {
        SimpleRBNode x = node;
        SimpleRBNode y = leaf;
        while (x != leaf) {
            y = x;
            x = x.left;
        }
        if (y != leaf)
            return y;
        return node;
    }

    private void RBTran(SimpleRBNode u, SimpleRBNode v) {
        if (u.parent == leaf)
            root = v;
        else if (u == u.parent.left)
            u.parent.left = v;
        else if (u == u.parent.right)
            u.parent.right = v;
        v.parent = u.parent;
    }

    private void RotateLeft(SimpleRBNode<V> x) {
        SimpleRBNode y = x.right;
        x.right = y.left;
        if (y.left != leaf) y.left.parent = x;

        y.parent = x.parent;

        if (x.parent == leaf) root = y;
        else if (x.parent.left == x) x.parent.left = y;
        else if (x.parent.right == x) x.parent.right = y;

        y.left = x;
        x.parent = y;
    }

    private void RotateRight(SimpleRBNode<V> x) {
        SimpleRBNode y = x.left;
        x.left = y.right;
        if (y.right != leaf)
            y.right.parent = x;
        y.parent = x.parent;
        if (x.parent == leaf) root = y;
        else if (x.parent.left == x) x.parent.left = y;
        else x.parent.right = y;
        y.right = x;
        x.parent = y;
    }

    public void Print() {
        Print(root);
    }

    private void Print(SimpleRBNode node) {
        String dir = "\nroot";
        if (node.parent != leaf) {
            if (node.parent.left == node)
                dir = "left";
            else
                dir = "right";
        }
        System.out.printf("%s:%d,%s,%s\n", dir, node.key, node.value, node.color);

        if (node.left != leaf)
            Print(node.left);
        if (node.right != leaf)
            Print(node.right);
    }

    public enum RBColor {
        RED(0), BLACK(1);
        private int value;

        private RBColor(int value) {
            this.value = value;
        }
    }

    public class SimpleRBNode<V> implements Comparable {
        private SimpleRBNode<V> left;
        private SimpleRBNode<V> right;
        private SimpleRBNode<V> parent;

        private int key;
        private V value;
        private RBColor color;

        public SimpleRBNode(int key, V value, SimpleRBNode<V> defaultLinkNode) {
            this.key = key;
            this.value = value;
            this.left = defaultLinkNode;
            this.right = defaultLinkNode;
            this.parent = defaultLinkNode;
            this.color = RBColor.RED;
        }

        @Override
        public int hashCode() {
            return key;
        }

        @Override
        public String toString() {
            return Integer.toString(key);
        }

        @Override
        public int compareTo(Object o) {
            return this.key - o.hashCode();
        }
    }

    final SimpleRBNode<V> leaf;
    private SimpleRBNode<V> root;
}

原文地址:https://www.cnblogs.com/liufu627/p/12142870.html

时间: 2024-11-13 08:14:15

红黑树新解(删除)的相关文章

红黑树之删除节点

红黑树之删除节点 上一篇文章中讲了如何向红黑树中添加节点,也顺便创建了一棵红黑树.今天写写怎样从红黑树中删除节点. 相比于添加节点,删除节点要复杂的多.不过我们慢慢梳理,还是能够弄明白的. 回顾一下红黑树的性质 红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色.在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 节点是红色或黑色. 根节点是黑色. 每个叶节点(这里的叶节点是指NULL节点,在<算法导论>中这个节点叫哨兵节点,除了颜色属性外,其他属性值都为任

红黑树(3) - 删除操作

在本系列的前面两篇文章中,已经介绍了红黑树以及其插入操作.具体可参考下面两个链接: 红黑树(1) - 介绍 红黑树(2) - 插入操作 1.删除操作介绍 类似于插入操作,红黑树进行删除节点时,也使用重新着色以及旋转这两种方式,来维护它的属性.在插入操作中,我们主要是依靠检测叔节点的颜色来决定哪种场景.在删除操作中,我们使用检测兄弟的颜色,来决定是哪种场景. 在插入操作中,最常见的违反红黑树属性的一种情况是存在两个连续的红色节点.而在删除操作中,常见的情况是,当删除节点是黑色时,会影响从根节点到叶

红黑树的删除操作详解

注:本文转载自博客园,博主原址:http://www.cnblogs.com/tongy0/p/5460623.html,感谢博主帮我弄清楚了红黑树删除操作,转载做收藏用. 红黑树的删除操作 1:节点命名约定 D表示要被删除的节点.即:取 Delete 的首字母: P 表示父节点.即:取 Parent 的首字母: S表示兄弟姐妹节点.即:取 Sibling的首字母: U表示叔伯节点.即:取Uncle的首字母: G表示祖父节点.即:取 Grandfather的首字母: L表示左树.即:取Left的

红黑树插入删除节点过程分析 &amp;&amp; C代码实现

红黑树的插入和删除规则: 红黑树的五个性质 1.    每个节点要么是红的,要么是黑的 2.    根节点时黑色的 3.    每个叶节点(叶节点既指树尾端NIL指针或NULL节点)是黑色的 4.    如果一个节点时红的,那么它的两个儿子都是黑色的 5.    对每个节点,其到叶节点树尾端NIL指针的每一条路径都包含相同数目的黑节点 这里所说的"叶节点"或者"NULL节点",它不包含数据而只充当树在此结束的知识. 二叉树的左旋和右旋这里不再讲解 红黑树的插入操作:

数据结构——红黑树的删除节点操作

1. 红黑树的删除操作过程分析 1. 首先看一下普通搜索二叉树的删除操作,普通搜索二叉树删除结点找替代结点有3种情情景: 情景1:删除结点无子结点,直接删除 情景2:删除结点只有一个子结点 情景3:删除结点有两个子结点 在这里有一个重要的思路:删除结点被替代后,在不考虑结点的键值的情况下,对于树来说,可以认为删除的是替代结点. 基于此,上面所说的3种二叉树的删除情景可以相互转换并且最终都是转换为情景1. 对于情景2:删除结点用其唯一的子结点替换,子结点替换为删除结点后,直接删除 对于情景3:删除

算法导论 红黑树 学习 删除(四)

版权声明:本文为博主原创文章,未经博主允许不得转载.技术博客 http://blog.csdn.net/stecdeng 技术交流群 群号码:324164944 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流 学习算法 还是建议看看算法导论 算法导论第三版 如果不看数学推导 仅看伪代码 难度还是适中 本系列只是记录我的学习心得 和伪代码转化代码的过程 深入学习 还是建议大家看看算法书籍 教程更加系统. 本文参考算法导论第13章节 红黑树 代码由本人写成 转载请标明出处 先看看不做

红黑树的删除和添加节点

操作 因为每一个红黑树也是一个特化的二叉查找树,因此红黑树上的只读操作与普通二叉查找树上的只读操作相同.然而,在红黑树上进行插入操作和删除操作会导致不再符合红黑树的性质.恢复红黑树的属性需要少量(O(log n))的颜色变更(实际是非常快速的)和不超过三次树旋转(对于插入操作是两次).虽然插入和删除很复杂,但操作时间仍可以保持为 O(log n) 次. 插入 我们首先以二叉查找树的方法增加节点并标记它为红色.(如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的

红黑树新解(插入)

1.  简介 红黑树是一种自平衡二叉查找树,在查找,插入和删除几个方面,性能都可以做到O(lgN). 那怎么实现呢,首先要先看看红黑树的5个特性,只有满足这5个特性,才是红黑树. 每个结点都有父结点(parent),左子结点(left)和右子结点(right), root的父结点是leaf结点. 下图便是一个简单的红黑树, 60为根结点,60的左子结点为30,60的右子结点为80,60的父结点为leaf结点: 30的父结点为60,30的左子结点和右子结点为leaf结点: 80的父结点为60,80

第八章&#160;高级搜索树 (xa4)红黑树:删除

原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/10249055.html