红黑树的插入删除

这段代码详细展示了红黑树中插入和删除节点后的平衡调整操作。插入节点时,根据节点颜色和父节点位置进行不同旋转和变色操作。删除节点时,处理二节点、三节点和四节点的情况,通过旋转和变色保持红黑树性质。整个过程涉及前驱节点、后继节点的寻找以及节点颜色和旋转的管理。
摘要由CSDN通过智能技术生成

插入:

向二节点插:直接插入

向三节点插:三个节点构成三角,直接插

                      三个节点构成直线,变色旋转一次

                      三个节点构成折线,变色一次,旋转两次

向四节点插:父辈节点变黑,爷爷节点变红

 

/**
     * 对插入的节点进行调整
     * @param node
     */
    private void fixAfterPut(Node<K,V> node) {
        //node的父节点是爷爷的左孩子
        while (node.parent != null && node.parent.color == RED) {
            if(parentOf(node) == leftOf(parentOf(parentOf(node)))) {
                Node uncle = parentOf(parentOf(node)).right;
                if(colorOf(uncle) == RED) {
                    setColor(parentOf(node), BLACK);
                    setColor(uncle, BLACK);
                    node = parentOf(parentOf(node));
                    if(node != root) {
                        setColor(node, RED);
                    }
                } else {
                    if(rightOf(parentOf(node)) == node) {
                        node = parentOf(node);
                        leftRotate(node);
                    }
                    setColor(parentOf(node), BLACK);
                    setColor(parentOf(parentOf(node)), RED);
                    rightRotate(parentOf(parentOf(node)));
                }
            } else {
                //node的父节点是爷爷的右孩子
                Node uncle = parentOf(parentOf(node)).left;
                if(colorOf(uncle) == RED) {
                    setColor(parentOf(node), BLACK);
                    setColor(uncle, BLACK);
                    node = parentOf(parentOf(node));
                    if(node != root) {
                        setColor(node, RED);
                    }

                } else {
                    if(leftOf(parentOf(node)) == node) {
                        node = parentOf(node);
                        rightRotate(node);
                    }
                    setColor(parentOf(node), BLACK);
                    setColor(parentOf(parentOf(node)), RED);
                    leftRotate(parentOf(parentOf(node)));
                }
            }
        }
    }

删除:若被删除节点有两个子节点,找其前驱或后继节点替代

若删除的节点对应234树是三节点或四节点删除,红色直接删除,黑色则找其子节点代替变黑

若删除的节点对应234树是二节点删除,需要调整,找到真正的兄弟节点,向兄弟节点借节点平衡黑色

        若兄弟有1个子节点,该子节点与兄弟与父节点构成直线,直接变色旋转,若构成折线,需变色旋转两次。若兄弟有2个子节点,直接变色旋转。

 

        若兄弟无子节点,兄弟变红,若父亲为红色,父亲变黑维持平衡结束,否则父亲向其兄弟借,借到平衡结束,否则父亲兄弟变黑,重复此过程

二节点删除调整代码:

private void fixAfterRemove(Node node) {
        while (colorOf(node) != RED && node != root) {
            //node为左孩子
            if (node == leftOf(node.parent)) {
                Node brother = rightOf(node.parent);
                if (colorOf(brother) == RED) {
                    setColor(brother, BLACK);
                    setColor(parentOf(node), RED);
                    leftRotate(parentOf(node));
                    brother = rightOf(parentOf(node));
                }
                //兄弟节点有孩子节点
                if (colorOf(leftOf(brother)) == BLACK && colorOf(rightOf(brother)) == BLACK) {
                    setColor(brother, RED);
                    node = node.parent;
                } else {
                    if (leftOf(brother) != null && rightOf(brother) == null) {
                        setColor(brother, RED);
                        setColor(brother.left, BLACK);
                        rightRotate(brother);
                        brother = rightOf(parentOf(node));
                    }
                    setColor(brother, colorOf(parentOf(node)));
                    setColor(rightOf(brother), BLACK);
                    setColor(parentOf(node), BLACK);
                    leftRotate(parentOf(node));
                    node = root;
                }

            } else {
                Node brother = leftOf(node.parent);
                if (colorOf(brother) == RED) {
                    setColor(brother, BLACK);
                    setColor(parentOf(node), RED);
                    rightRotate(parentOf(node));
                    brother = leftOf(parentOf(node));
                }
                //兄弟节点有孩子节点
                if (colorOf(leftOf(brother)) == BLACK && colorOf(rightOf(brother)) == BLACK) {
                    setColor(brother, RED);
                    node = node.parent;
                } else {
                    if (rightOf(brother) != null && leftOf(brother) == null) {
                        setColor(brother, RED);
                        setColor(rightOf(brother), BLACK);
                        leftRotate(brother);
                        brother = leftOf(parentOf(node));
                    }
                    setColor(brother, colorOf(parentOf(node)));
                    setColor(leftOf(brother), BLACK);
                    setColor(parentOf(node), BLACK);
                    rightRotate(parentOf(node));
                    node = root;
                }
            }
        }
        setColor(node, BLACK);

    }

全部代码:

package tree;

import java.util.ArrayList;
import java.util.List;

public class RBTree<K extends Comparable<K>, V> {

    private static final boolean RED = false;
    private static final boolean BLACK = true;
    private Node<K, V> root;

    public boolean contains(K key) {
        return find(key) != null;
    }
    private Node find(K key) {
        if (key == null) return null;
        Node node = root;
        while (node != null) {
            int compare = key.compareTo((K)node.key);
            if(compare == 0) return node;
            else if(compare > 0) node = node.right;
            else node = node.left;
        }
        return null;
    }
    public V remove(K key) {
        Node node = getNode(key);
        if(node == null) return null;
        V oldValue = (V)node.value;
        delete(node);

        return oldValue;
    }

    private void delete(Node node) {
        if(node == null) return;
        //node有两个孩子节点, 找其后继节点替换,并删除后继节点
        if(node.left != null && node.right != null) {
//            Node sucessor = sucessor(node);
            Node sucessor = predecessor(node);
            node.key = sucessor.key;
            node.value = sucessor.value;
            node = sucessor;
        }
        Node replace = node.left == null? node.right : node.left;
        //node没有孩子节点,直接删除
        if (replace == null) {
            if (node == root) {
                root = null;
                return;
            }
            if (node.color == BLACK) {
                //要删除黑色叶子节点,需要调整
                fixAfterRemove(node);
            }
            if (node.parent.left == node) node.parent.left = null;
            else if (node.parent.right == node) node.parent.right = null;
            node.parent = null;
        } else {
            //node有一个孩子节点,将孩子节点和父节点连接
            replace.parent = node.parent;
            if (node == root) {
                root = replace;
            } else if (node.parent.left == node) {
                node.parent.left = replace;
            } else if (node.parent.right == node) {
                node.parent.right = replace;
            }
            node.right = node.left = node.parent = null;
            if (node.color == BLACK) {
                //相当于2-3-4树三节点的删除,replace一定是红色,直接染黑
                replace.color = BLACK;
            }
        }
    }

    private void fixAfterRemove(Node node) {
        while (colorOf(node) != RED && node != root) {
            //node为左孩子
            if (node == leftOf(node.parent)) {
                Node brother = rightOf(node.parent);
                if (colorOf(brother) == RED) {
                    setColor(brother, BLACK);
                    setColor(parentOf(node), RED);
                    leftRotate(parentOf(node));
                    brother = rightOf(parentOf(node));
                }
                //兄弟节点有孩子节点
                if (colorOf(leftOf(brother)) == BLACK && colorOf(rightOf(brother)) == BLACK) {
                    setColor(brother, RED);
                    node = node.parent;
                } else {
                    if (leftOf(brother) != null && rightOf(brother) == null) {
                        setColor(brother, RED);
                        setColor(brother.left, BLACK);
                        rightRotate(brother);
                        brother = rightOf(parentOf(node));
                    }
                    setColor(brother, colorOf(parentOf(node)));
                    setColor(rightOf(brother), BLACK);
                    setColor(parentOf(node), BLACK);
                    leftRotate(parentOf(node));
                    node = root;
                }

            } else {
                Node brother = leftOf(node.parent);
                if (colorOf(brother) == RED) {
                    setColor(brother, BLACK);
                    setColor(parentOf(node), RED);
                    rightRotate(parentOf(node));
                    brother = leftOf(parentOf(node));
                }
                //兄弟节点有孩子节点
                if (colorOf(leftOf(brother)) == BLACK && colorOf(rightOf(brother)) == BLACK) {
                    setColor(brother, RED);
                    node = node.parent;
                } else {
                    if (rightOf(brother) != null && leftOf(brother) == null) {
                        setColor(brother, RED);
                        setColor(rightOf(brother), BLACK);
                        leftRotate(brother);
                        brother = leftOf(parentOf(node));
                    }
                    setColor(brother, colorOf(parentOf(node)));
                    setColor(leftOf(brother), BLACK);
                    setColor(parentOf(node), BLACK);
                    rightRotate(parentOf(node));
                    node = root;
                }
            }
        }
        setColor(node, BLACK);

    }

    private Node getNode(K key) {
        if (key == null) return null;
        Node<K, V> node = root;
        while (node != null) {
            int compare = key.compareTo(node.key);
            if(compare == 0) return node;
            else if (compare > 0) {
                node = node.right;
            } else {
                node = node.left;
            }
        }
        return null;
    }

    /**
     * 查找前驱节点
     * @param node
     * @return
     */
    private Node predecessor(Node node) {
        if(node == null || node.left == null) return null;
        node = node.left;
        Node pre = node;
        while (node != null) {
            pre = node;
            node = node.right;
        }
        return pre;
    }

    /**
     * 查找后继节点
     * @param node
     * @return
     */
    private Node sucessor(Node node) {
        if(node == null || node.right == null) return null;
        node = node.right;
        Node pre = node;
        while (node != null) {
            pre = node;
            node = node.left;
        }
        return pre;
    }
    public Node getRoot() {
        return root;
    }
    /**
     * 按升序返回搜索二叉树的值
     * @return
     */
    public List<Entry<K, V>> list() {
        List<Entry<K, V>> list = new ArrayList<>();
        ldr(root, list);
        return list;
    }

    private void ldr(Node<K, V> node, List<Entry<K, V>> list) {
        if (node == null) return;
        ldr(node.left, list);
        list.add(new Entry<K, V>(node.key, node.value));
        ldr(node.right, list);
    }
    public void put(K key, V value) {
        if(root == null) {
            root = new Node<K, V>(null, null, null, BLACK, key, value);
            return;
        }
        Node node = root;
        Node p = null;
        int compare = 0;
        while (node != null) {
           compare = node.key.compareTo(key);
            p = node;
            if(compare > 0) {
                node = node.left;
            } else if(compare < 0) {
                node = node.right;
            } else {
                node.setValue(value);
                return;
            }
        }
        Node<K, V> insertNode = new Node(p, null, null, RED, key, value);
        if (compare > 0) {
            p.left = insertNode;
        } else {
             p.right = insertNode;
        }
        //调整
        fixAfterPut(insertNode);


    }

    /**
     * 对插入的节点进行调整
     * @param node
     */
    private void fixAfterPut(Node<K,V> node) {
        //node的父节点是爷爷的左孩子
        while (node.parent != null && node.parent.color == RED) {
            if(parentOf(node) == leftOf(parentOf(parentOf(node)))) {
                Node uncle = parentOf(parentOf(node)).right;
                if(colorOf(uncle) == RED) {
                    setColor(parentOf(node), BLACK);
                    setColor(uncle, BLACK);
                    node = parentOf(parentOf(node));
                    if(node != root) {
                        setColor(node, RED);
                    }
                } else {
                    if(rightOf(parentOf(node)) == node) {
                        node = parentOf(node);
                        leftRotate(node);
                    }
                    setColor(parentOf(node), BLACK);
                    setColor(parentOf(parentOf(node)), RED);
                    rightRotate(parentOf(parentOf(node)));
                }
            } else {
                //node的父节点是爷爷的右孩子
                Node uncle = parentOf(parentOf(node)).left;
                if(colorOf(uncle) == RED) {
                    setColor(parentOf(node), BLACK);
                    setColor(uncle, BLACK);
                    node = parentOf(parentOf(node));
                    if(node != root) {
                        setColor(node, RED);
                    }

                } else {
                    if(leftOf(parentOf(node)) == node) {
                        node = parentOf(node);
                        rightRotate(node);
                    }
                    setColor(parentOf(node), BLACK);
                    setColor(parentOf(parentOf(node)), RED);
                    leftRotate(parentOf(parentOf(node)));
                }
            }
        }

    }

    private void setColor(Node node, boolean color) {
        if (node != null) {
            node.color = color;
        }
    }
    private boolean colorOf(Node node) {
        return node == null? BLACK : node.color;
    }

    private Node parentOf(Node node) {
        return node == null? null : node.parent;
    }

    private Node leftOf(Node node) {
        return node == null? null : node.left;
    }

    private Node rightOf(Node node) {
        return  node == null? null : node.right;
    }

    /**
     * 左旋
     * @param node
     */
    private void leftRotate(Node node) {
        if (node != null && node.right != null) {
            Node r = node.right;
            node.right = r.left;
            if(r.left != null) {
                r.left.parent = node;
            }
            r.left = node;
            Node parent = node.parent;
            r.parent = parent;
            node.parent = r;
            if(parent == null) {
                root = r;
            } else if(parent.left == node) {
                parent.left = r;
            } else {
                parent.right = r;
            }
        }
    }

    /**
     * 右旋
     * @param node
     */
    private void rightRotate(Node node) {
        if (node != null && node.left != null) {
            Node l = node.left;
            node.left = l.right;
            if(l.right != null) {
                l.right.parent = node;
            }
            Node parent = node.parent;
            l.right = node;
            node.parent = l;
            l.parent = parent;
            if(parent == null) {
                root = l;
            } else if(parent.left == node) {
                parent.left = l;
            } else {
                parent.right = l;
            }
        }
    }
    static class Entry<K, V> {
        private K key;
        private V value;

        public Entry() {
        }

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "Entry{" +
                    "key=" + key +
                    ", value=" + value +
                    '}';
        }
    }
    static class Node<K extends Comparable<K>, V> {
        private Node parent;
        private Node left;
        private Node right;
        private boolean color;
        private K key;
        private V value;

        public Node getParent() {
            return parent;
        }

        public void setParent(Node parent) {
            this.parent = parent;
        }

        public Node getLeft() {
            return left;
        }

        public void setLeft(Node left) {
            this.left = left;
        }

        public Node getRight() {
            return right;
        }

        public void setRight(Node right) {
            this.right = right;
        }

        public boolean isColor() {
            return color;
        }

        public void setColor(boolean color) {
            this.color = color;
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        public Node(Node parent, Node left, Node right, boolean color, K key, V value) {
            this.parent = parent;
            this.left = left;
            this.right = right;
            this.color = color;
            this.key = key;
            this.value = value;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值