红黑树代码实现过程详解

本文详细介绍了红黑树的节点定义、树结构验证、红黑树类的旋转、新增节点平衡调整以及删除节点的处理。通过节点颜色定义、树的打印方法以及旋转和平衡策略,帮助理解红黑树的运作机制。
摘要由CSDN通过智能技术生成

效果

在这里插入图片描述

一.红黑树节点类定义

public class Node {
   	

}

1.1 颜色使用Boolen定义

    public static boolean BLACK = true;
    public static boolean RED = false;

1.2 每一个节点有值、父节点、左右节点、颜色等属性

private int value;
    private Node left;
    private Node right;
    private Node parent;

    private Boolean color;

1.3 构造方法和toSting方法

tostring方法用于显示树结构显示的字符串

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

    @Override
    public String toString() {
   
        String colorStr = color ? "B" : "R";
        return value + colorStr;
    }

二.树打印类,用于验证树结构是否正确

目标效果:
在这里插入图片描述

打印树结构,我们使用二维数组来组成全空格的画板,将树结构写入二维数组的相应位置中显示出来

public class TreeOperation {
   
}

2.1 获取树高度

获取树高度用于确定二维数组的高度

    // 用于获得树的层数
    public static int getTreeDepth(Node root) {
   
        return root == null ? 0 : (1 + Math.max(getTreeDepth(root.getLeft()), getTreeDepth(root.getRight())));
    }

2.2 写二维数组

这个方法是递归方法,将每个节点写入二维数组,从树的根节点开始执行,递归执行到每一个节点。
rowIndex是节点要写入的行坐标,columnIndex是列坐标,res是存储的二维数组,treeDepth是树高

主要逻辑就是先确定一个节点的位置,根据这个节点位置,画出左右枝干,左右枝干就在节点下层的两侧,具体宽度可以调节,再根据枝干位置,给出子节点的位置,以此类推

还有一定要注意,节点与枝干的宽度是递减的,不然节点写入二维数组的位置会重叠

private static void writeArray(Node currNode, int rowIndex, int columnIndex, String[][] res, int treeDepth) {
   
        // 保证输入的树不为空
        if (currNode == null) {
   
            return;
        }
        // 先将当前节点保存到二维数组中
        // rowIndex是层数,columnIndex是列数
        res[rowIndex][columnIndex] = String.valueOf(currNode.getValue() + (currNode.getColor() ? "B" : "R") + "");

        // 计算当前位于树的第几层
        //因为还有斜线,如果行数+1除以2等于数据层数,rowIndex由于下面代码的判断会跳过单数数字
        int currLevel = ((rowIndex + 1) / 2);
        // 若到了最后一层,则返回
        if (currLevel == treeDepth) {
   
            return;
        }
        // 计算当前行到下一行,每个元素之间的间隔(下一行的列索引与当前元素的列索引之间的间隔)
        // -1是由于层数是从0开始的,treeDepth是从1开始的,因为上面的宽度要容纳很多,所以上面的间隔要大于下面的隔间
        //越是子节点越小间隔
        int gap = treeDepth - currLevel - 1;
//        int gap = 4;
        // 对左儿子进行判断,若有左儿子,则记录相应的"/"与左儿子的值
        if (currNode.getLeft() != null) {
   
            // columnIndex-与上一层元素的间隔
            if (rowIndex == 0) {
   
                res[rowIndex + 1][columnIndex - gap * 5] = "/";
                writeArray(currNode.getLeft(), rowIndex + 2, columnIndex - gap * 5, res, treeDepth);
            } else {
   
                res[rowIndex + 1][columnIndex - gap] = "/";
                writeArray(currNode.getLeft(), rowIndex + 2, columnIndex - gap * 3, res, treeDepth);
            }
        }

        // 对右儿子进行判断,若有右儿子,则记录相应的"\"与右儿子的值
        if (currNode.getRight() != null) {
   
            if (rowIndex == 0) {
   
                res[rowIndex + 1][columnIndex + gap * 5] = "\\";
                writeArray(currNode.getRight(), rowIndex + 2, columnIndex + gap * 5, res, treeDepth);
            } else {
   
                res[rowIndex + 1][columnIndex + gap] = "\\";
                writeArray(currNode.getRight(), rowIndex + 2, columnIndex + gap * 3, res, treeDepth);
            }
        }
    }

2.3 打印方法

传入根节点进行打印树结构。
难理解处:
1.int arrayHeight = treeDepth * 2 - 1;
高度每个节点都有枝干,最后一层节点没有枝干,少一层的枝干,所以是2*树高-1

2.int arrayWidth = (2 << (treeDepth - 2)) * 9 + 1;
宽度,每一层的节点数是2^(n-1)=2 << (treeDepth - 2), 乘以9是每个节点+空格需要9个空格的位置,+1是开始的空格。9和1可以自己调整。

 public static void show(Node root) {
   
        if (root == null) {
   
            System.out.println("EMPTY!");
        }
        // 得到树的深度
        int treeDepth = getTreeDepth(root);

        // 最后一行的宽度为2的(n - 1)次方乘3,再加1
        // 作为整个二维数组的宽度
        //因为数据需要treeDepth层,加上画线treeDepth-1(最后一层数据不用画线)
        int arrayHeight = treeDepth * 2 - 1;
        //2 <<N :2*2^N    2*2^treeDepth-2=2^n-1  第一层是1 第二层是2,第五层就是16
        //乘以3是每一个数据要占用+旁边的空格要占用三个?
        int arrayWidth = (2 << (treeDepth - 2)) * 9 + 1;
        // 用一个字符串数组来存储每个位置应显示的元素
        String[][] res = new String[arrayHeight][arrayWidth];
        // 对数组进行初始化,默认为一个空格
        for (int i = 0; i < arrayHeight; i++) {
   
            for (int j = 0; j < arrayWidth; j++) {
   
                res[i][j] = " ";
            }
        }

        // 从根节点开始,递归处理整个树
        // res[0][(arrayWidth + 1)/ 2] = (char)(root.val + 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值