红黑树-java实现

74 阅读1分钟

直接看代码注释

package com.zzqfsy.algorithm.redblacktree;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 1. 红黑树的特点
 * 每个结点不是红色就是黑色。
 * 不可能有连在一起的红色结点。
 * 根结点一定为黑色。
 * 每个红色结点的两个子结点都是黑色。
 * <p>
 * 2. 旋转与颜色变换规则
 * 2.1 颜色变换
 * 当前结点的父亲是红色,且叔叔结点也是红色时:
 * <p>
 * 把父结点设为黑色
 * 把叔叔结点设为黑色
 * 把爷爷结点设为红色
 * 把指针定义到爷爷结点上,当有违红黑树和特点时再进行变色或旋转
 */
public class RedBlackTree {

    public static void main(String[] args) {
        RedBlackTree redBlackTree = new RedBlackTree();
        redBlackTree.insert(3);
        redBlackTree.insert(10);
        redBlackTree.insert(6);
        redBlackTree.insert(1);
        redBlackTree.insert(5);

        redBlackTree.insert(4);
        redBlackTree.insert(4);
        redBlackTree.insert(4);

        redBlackTree.insert(12);
//        for (int i = 0; i < 100; i++) {
            redBlackTree.insert(15);
//        }

        System.out.println("Root:" + redBlackTree.getRoot());
        System.out.println(redBlackTree.getBeforeList(redBlackTree));
    }

    /**
     * 红色
     */
    private final int RED = 0;
    /**
     * 黑色
     */
    private final int BLACK = 1;
    /**
     * 根结点
     */
    private Node root;

    /**
     * 内部类表示结点
     */
    private class Node {
        int data;
        int color;
        Node left;
        Node right;
        Node parent;

        Node(int data) {
            this.data = data;
            color = RED;
        }

        public int height(){
            return Math.max(left == null ? 0 : left.height(),
                    right == null ? 0 : right.height()) + 1;
        }

        @Override
        public String toString() {
            return "Node{data=" + data + ", color=" + (color == RED ? "red" : "black") + '}';
        }
    }

    /**
     * 获取Node结点
     */
    public Node getInstanceNode(int data) {
        return new Node(data);
    }

    /**
     * 插入值
     *
     * @param data 数值
     */
    public void insert(int data) {
        // region insert node
        Node node = new Node(data);

        //插入根结点
        if (root == null) {
            node.color = BLACK;
            root = node;
            return;
        }

        Node parent = root;
        Node son;

        //左子树
        if (data < parent.data) {
            son = parent.left;
        } else {
            son = parent.right;
        }
        //递归
        while (son != null) {
            parent = son;
            if (data < parent.data) {
                son = parent.left;
            } else {
                son = parent.right;
            }
        }
        if (data < parent.data) {
            parent.left = node;
        } else {
            parent.right = node;
        }
        node.parent = parent;
        // endregion

        //颜色变换
        colorConvert(node);
    }

    /**
     * 颜色变换,使整体符合红黑树规则
     */
    public void colorConvert(Node node) {
        Node parent;
        Node grandpa;

        //当父结点不为空且颜色为红色(插入节点都为红色,保证没有连续连接的红色节点来消除高度)
        while ((parent = node.parent) != null && parent.color == RED) {
            grandpa = parent.parent;
            //如果父亲是爷爷的左子树
            if (grandpa.left == parent) {
                //获取叔叔结点
                Node uncle = grandpa.right;
                //如果叔叔结点不为空且颜色为红色
                if (uncle != null && uncle.color == RED) {
                    // 颜色标级,父一级为黑色,祖父为红色
                    parent.color = BLACK;
                    uncle.color = BLACK;
                    grandpa.color = RED;
                    node = grandpa;
                    continue;
                }
                if (node == parent.right) {
                    //左旋
                    leftRotate(parent);
                    //左旋后父子身份互换
                    Node temp = node;
                    node = parent;
                    parent = temp;
                }
                // 颜色标级,父一级为黑色,祖父为红色
                parent.color = BLACK;
                grandpa.color = RED;
                //右旋
                rightRotate(grandpa);
            } else {
                //如果父亲是爷爷的右子树
                Node uncle = grandpa.left;
                if (uncle != null && uncle.color == RED) {
                    // 颜色标级,父一级为黑色,祖父为红色
                    parent.color = BLACK;
                    uncle.color = BLACK;
                    grandpa.color = RED;
                    node = grandpa;
                    continue;
                }
                if (node == parent.left) {
                    //右旋
                    rightRotate(parent);
                    //右旋后父子身份互换
                    Node temp = node;
                    node = parent;
                    parent = temp;
                }
                // 颜色标级,父一级为黑色,祖父为红色
                parent.color = BLACK;
                grandpa.color = RED;
                //左旋
                leftRotate(grandpa);
            }
        }
        root.color = BLACK;
    }

    /**
     * 左旋
     */
    private void leftRotate(Node node) {
        Node right = node.right;
        Node parent = node.parent;
//         — (左旋处理爸爸,【父亲节点】的父亲为【祖父节点】的父亲)
        if (parent == null) {
            root = right;
            right.parent = null;
        } else {
            if (parent.left != null && parent.left == node) {
                parent.left = right;
            } else {
                parent.right = right;
            }
            right.parent = parent;
        }
//        ——(左旋处理孩子,【父亲节点】的左节点为【祖父节点】的右节点)
        node.right = right.left;
        if (right.left != null) {
            right.left.parent = node;
        }
//       ——(左旋处理自身,【父亲节点】的左节点为【祖父节点】)
        node.parent = right;
        right.left = node;
    }

    /**
     * 右旋
     */
    private void rightRotate(Node node) {
        Node left = node.left;
        Node parent = node.parent;

//      — (右旋处理爸爸,【父亲节点】的父亲为【祖父节点】的父亲)
        if (parent == null) {
            root = left;
            left.parent = null;
        } else {
            if (parent.left != null && parent.left == node) {
                parent.left = left;
            } else {
                parent.right = left;
            }
            left.parent = parent;
        }
//      ——(右旋处理孩子,【父亲节点】的右节点为【祖父节点】的左节点)
        node.left = left.right;
        if (left.right != null) {
            left.right.parent = node;
        }
//      ——(右旋处理自身,【父亲节点】的右节点为【祖父节点】)
        node.parent = left;
        left.right = node;
    }

    private Map<Integer, List<String>> beforeListMap = new HashMap<>();

    /**
     * 前序遍历
     */
    private void beforeTraversal(Node node, int deep) {
        if (node != null) {
            List<String> beforeList = beforeListMap.get(deep);
            if (beforeList == null || beforeList.isEmpty()){
                beforeList = new ArrayList<>();
            }
            beforeList.add(node.data + "-" + (node.color == RED ? "red" : "black") + "-" + node.height() + "-" + deep);
            beforeListMap.put(deep, beforeList);
            deep = deep + 1;
            beforeTraversal(node.left, deep);
            beforeTraversal(node.right, deep);
        }
    }

    /**
     * 获取前序遍历后的集合
     */
    public Map<Integer, List<String>> getBeforeList(RedBlackTree tree) {
        tree.beforeTraversal(tree.getRoot(), 0);
        return beforeListMap;
    }

    public Node getRoot() {
        return root;
    }
}