红黑树新解(删除)

Posted liufu627

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树新解(删除)相关的知识,希望对你有一定的参考价值。

 

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("
left:case1
");
                }
                if (w.left.color == RBColor.BLACK && w.right.color == RBColor.BLACK) {
                    w.color = RBColor.RED;
                    x = x.parent;
                    //System.out.printf("
left:case2
");
                }
                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("
left:case3
");
                }
                else {
                    w.color = w.parent.color;
                    x.parent.color = RBColor.BLACK;
                    w.right.color = RBColor.BLACK;
                    RotateLeft(x.parent);
                    x = root;
                    //System.out.printf("
left:case4
");
                }
            } 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("
right:case1
");
                }
                if (w.right.color == RBColor.BLACK && w.left.color == RBColor.BLACK) {
                    w.color = RBColor.RED;
                    x = x.parent;
                    //System.out.printf("
right:case2
");
                }
                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("
right:case3
");
                }
                else {
                    w.color = w.parent.color;
                    x.parent.color = RBColor.BLACK;
                    w.left.color = RBColor.BLACK;
                    RotateRight(x.parent);
                    x = root;
                    //System.out.printf("
right:case4
");
                }
            }
        }
        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 = "
root";
        if (node.parent != leaf) {
            if (node.parent.left == node)
                dir = "left";
            else
                dir = "right";
        }
        System.out.printf("%s:%d,%s,%s
", 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;
}

 

以上是关于红黑树新解(删除)的主要内容,如果未能解决你的问题,请参考以下文章

红黑树插入与删除完整代码(dart语言实现)

红黑树旋转

红黑树的旋转查找和删除(附源代码)

使用红黑树的字典 - 删除错误

算法导论 红黑树 学习 删除

C++-红黑树的插入和删除实现