手写红黑树

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.*;

public class RedBlackTree {
    //树的根节点
    private RedBlackTreeNode root;

    //红黑标记
    private static final boolean red = false;
    private static final boolean black = true;
    //输出时用于存储节点信息
    Map<Integer,String> map ;


    /**
     * @program:
     * @return:
     * @description:插入一个节点
     **/
    public void insert(int key){
        RedBlackTreeNode node = new RedBlackTreeNode();
        node.setColor(red);
        node.setKey(key);
        //保存节点
        save(node);
    }

    /**
    * @program:
    * @return:
    * @description:根据key的大小找出插入位置,调用check检查树进行调整
    **/

    private void save(RedBlackTreeNode node){
        //找出插入位置
        //当前遍历节点值
        RedBlackTreeNode parent = root;
        if(parent==null){
            node.setColor(black);
            root=node;
            return;
        }
        //待插入值
        int key = node.getKey();
        while(true){
            int nowNodeKey = parent.getKey();
            //相等则替代,key值相同value可能不同所以选择替代,虽然为了试验方便没有设置value
            if(key==nowNodeKey) {
                //继承被替代节点的值
                node.setColor(parent.isColor());
                node.setParent(parent.getParent());
                node.setLeft(parent.getLeft());
                node.setRight(parent.getRight());
                if (node.getParent() != null) {
                    //判断是它的哪个孩子
                    if (isLeft(node.getParent(), node.getKey())) {
                        node.getParent().setLeft(node);
                    } else {
                        node.getParent().setRight(node);
                    }
                }
                if (node.getLeft() != null) {
                    node.getLeft().setParent(node);
                }
                if (node.getRight() != null) {
                    node.getRight().setParent(node);
                }
                break;
            }else if(key<nowNodeKey){//key<nowNodeKey,遍历左树
                //左子树为空插入
                if(parent.getLeft()==null){
                    node.setParent(parent);
                    parent.setLeft(node);
                    break;
                }
                //左子树不为空
                parent = parent.getLeft();
            }else{
                //右子树为空插入
                if(parent.getRight()==null){
                    node.setParent(parent);
                    parent.setRight(node);
                    break;
                }
                //右子树不为空
                parent = parent.getRight();
            }
        }
        //插入完成,进行检查树的结构
        check(node);
    }
    //判断是不是左孩子
    private boolean isLeft(RedBlackTreeNode parent, int key){
        if(parent.getLeft()!=null&&parent.getLeft().getKey()==key){
            return true;
        }
        return false;
    }
    public void print(){
        //输出应该使用二维数组比较好,但是为了方便就使用map
        map=new HashMap<>();
        show(root,1);
        int[] start = {1};
        map.forEach((i,s)->{
            if(i>=(2<<(start[0]-1))){
                System.out.println();
                start[0]=start[0]+1;
            }
            System.out.print(i+":"+map.get(i));
        });
    }
    private void show(RedBlackTreeNode root,int index){
        if(root == null){
            return;
        }else{
            show(root.getLeft(),index*2);
            map.put(index,root.toString());
            show(root.getRight(),index*2+1);
        }
    }
    //严查祖上,不用担心没有三代,因为初始根节点为黑,当进行调整的时候肯定是第三层往下
    public void check(RedBlackTreeNode node){
        //根节点要保持为黑,为了方便每次执行不需要进行判断,直接赋值
        root.setColor(black);
        /*if(node==null){
            return;
        }*/
        RedBlackTreeNode parent = node.getParent();
        if(parent==null){
            return;
        }
        //如果父节点为黑,则不用管,直接return
        if(parent.isColor()){
            return;
        }
        RedBlackTreeNode grand = parent.getParent();
        RedBlackTreeNode uncle;
        if(isLeft(grand,parent.getKey())){
            uncle = grand.getRight();
        }else {
            uncle = grand.getLeft();
        }
        //如果父节点为红,而且父节点的兄弟节点也为红,则父节点的父节点变红,父节点和其兄弟变黑,check(父节点的父节点)
        if(uncle!=null&&!uncle.isColor()){
            grand.setColor(red);
            parent.setColor(black);
            uncle.setColor(black);
            check(grand);
        }else {
            //如果父节点为红但是其兄弟为黑,则parent变黑grand变红然后进行调整
            //如果父节点是左孩子且插入节点也是左孩子则顺时针调整,如果插入节点是右孩子先调整为左节点后再旋转,check(父节点)
            //如果父节点是右孩子且插入节点也是右孩子则顺时针调整,如果插入节点是左孩子先调整为右节点后再旋转,check(父节点)
            if (isLeft(grand, parent.getKey())) {
                if(!isLeft(parent, node.getKey())){
                    //转换后调整
                    changeToLeft(node,parent,grand);
                    parent=node;//转换后原来的node变成了parent
                }
                grand.setColor(red);
                parent.setColor(black);
                //调整
                leftAdjust(parent,grand);
                //check(parent.getParent());调整之后parent变成了grand而且是黑色和原来的grand一样那么肯定是合法的
            } else {
                if(isLeft(parent, node.getKey())){
                    //转换后调整
                    changeToRight(node,parent,grand);
                    parent=node;
                }
                grand.setColor(red);
                parent.setColor(black);
                //调整
                rightAdjust(parent,grand);
                //check(parent.getParent());
            }
        }
        return;
    }
    private void changeToLeft(RedBlackTreeNode node,RedBlackTreeNode parent,RedBlackTreeNode grand){
        grand.setLeft(node);
        node.setParent(grand);
        parent.setRight(node.getLeft());
        if(node.getLeft()!=null){
            node.getLeft().setParent(parent);
        }
        node.setLeft(parent);
        parent.setParent(node);
    }
    private void changeToRight(RedBlackTreeNode node,RedBlackTreeNode parent,RedBlackTreeNode grand){
        grand.setRight(node);
        node.setParent(grand);
        parent.setLeft(node.getRight());
        if(node.getRight()!=null){
            node.getRight().setParent(parent);
        }
        node.setRight(parent);
        parent.setParent(node);
    }
    private void leftAdjust(RedBlackTreeNode parent, RedBlackTreeNode grand){
        parent.setParent(grand.getParent());
        if (grand.getParent()!=null) {
            if (isLeft(grand.getParent(), grand.getKey())) {
                grand.getParent().setLeft(parent);
            }else {
                grand.getParent().setRight(parent);
            }
        }else {
            root=parent;
        }
        grand.setLeft(parent.getRight());
        if(parent.getRight()!=null){
            parent.getRight().setParent(grand);
        }
        parent.setRight(grand);
        grand.setParent(parent);
    }
    private void rightAdjust(RedBlackTreeNode parent,RedBlackTreeNode grand){
        parent.setParent(grand.getParent());
        if (grand.getParent()!=null) {
            if (isLeft(grand.getParent(), grand.getKey())) {
                grand.getParent().setLeft(parent);
            }else {
                grand.getParent().setRight(parent);
            }
        }else {//grand没有父节点证明grand是root
            root=parent;
        }
        grand.setRight(parent.getLeft());
        if(parent.getLeft()!=null){
            parent.getLeft().setParent(grand);
        }
        parent.setLeft(grand);
        grand.setParent(parent);
    }
}

public class RedBlackTreeNode {
    private RedBlackTreeNode parent;
    private RedBlackTreeNode left;
    private RedBlackTreeNode right;
    private int key;
    private boolean color;

    public RedBlackTreeNode getParent() {
        return parent;
    }

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

    public RedBlackTreeNode getLeft() {
        return left;
    }

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

    public RedBlackTreeNode getRight() {
        return right;
    }

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

    public int getKey() {
        return key;
    }

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

    public boolean isColor() {
        return color;
    }

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

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


import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        RedBlackTree redBlackTree = new RedBlackTree();
        Scanner scanner = new Scanner(System.in);
        int key;
        while(true){
            key= scanner.nextInt();
            /*if(key==0){
                redBlackTree.print();
                continue;
            }*/
            redBlackTree.insert(key);

            System.out.println("---------------------");
            redBlackTree.print();

        }
    }

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值