数据结构--树--红黑树--Java实现检验和删除

本文介绍了作者在周末完成的红黑树删除功能的Java代码实现,并进行了测试,未发现明显问题。文章提供了代码环境、红黑树合法性的检查方法以及删除节点的实现。此外,作者分享了相关代码资源,欢迎大家下载学习,同时欢迎指出可能的疏漏。
摘要由CSDN通过智能技术生成

写在前面

今儿个周末,终于有时间把前两天写的关于红黑树删除部分的代码进行测试,现在测试完了,暂没有发现问题,所以将代码分享出来,供大家参考学习.

注意:这次的检验与删除部分跟之前的查找和插入部分一脉相承,所以重复的部分我就不粘出来了,大家可以两篇文章一起看.

具体包已经上传,免费下载RedBlackTree.zip

水平有限,难免疏漏,欢迎指正.

代码部分

运行环境

jdk1.8

intellij idea ultimate 2020.2

检查红黑树是否合法

    /**
     * 检查红黑树是否合法
     *
     */
    public boolean checkTree() {

        TreeNode<V> node = rootNode;
        int number = 0;
        int blackNums1 = 0;
        int blackNums2;
        int count = 0;
        boolean isRedBlackTree = true;

        Map map = new HashMap<>();

        // 如果是空树
        if (node != null) {
            if (node.isRoot() && node.isRed()) {
                isRedBlackTree = false;
            }else {
                checkTreeMethod(node, number, map);
            }
        }

        for (Object key : map.keySet()) {
            count++;
            if (count == 1) {
                blackNums1 = (int) map.get(key);
            }else {
                blackNums2 = (int) map.get(key);
                if (blackNums1 != blackNums2) {
                    System.out.println("当前路径" + key + "上的黑色节点数是: " + map.get(key));
                    System.out.println("但是其它路径上的黑色节点数是: " + blackNums1);
                    isRedBlackTree = false;
                    break;
                }
            }
        }
        return isRedBlackTree;
    }

    private void checkTreeMethod(TreeNode<V> node, int number, Map map) {

        if (!node.isRed()) {
            number++;
        }
        if (node.getLeft() != null) {
            checkTreeMethod(node.getLeft(), number, map);
        }else {
            map.put(node.getKey() + "'s left", number);
        }
        if (node.getRight() != null) {
            checkTreeMethod(node.getRight(), number, map);
        }else {
            map.put(node.getKey() + "'s right", number);
        }
    }

删除节点

package com.srt.orange.test.Tree;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: cuijr
 * @email: 
 * @date: 2020-11-10 15:08
 * @description:
 */
public class RedBlackTree<V> {

    // 树的根节点
    private TreeNode<V> rootNode;

    /**
     * 查找
     * @param key
     * @param currentNode: the root node of the tree which you want to use
     */
    public TreeNode<V> find(int key,TreeNode<V> currentNode) {
        TreeNode<V> node = null;
        if (currentNode != null) {
            if (currentNode.getKey() == key) {
                return currentNode;
            }else if (currentNode.getKey() > key) {
                return find(key, currentNode.getLeft());
            }else {
                return find(key, currentNode.getRight());
            }
        }
        return node;
    }

    // turn left
    // node is the pivot
    private void turnLeft(TreeNode<V> node) throws CanNotTurnLeft {
        TreeNode<V> temp = null;
        if (node == null || node.getParent() == null) {
            throw new CanNotTurnLeft("you cannot turn left because short of valid treenode");
        }else {
            temp = node.getLeft();

            node.setLeft(node.getParent());
            node.setParent(node.getLeft().getParent());
            node.setLeft(node.getLeft().isLeft());

            node.getLeft().setParent(node);
            node.getLeft().setLeft(true);
            node.getLeft().setRight(temp);

            if (node.getParent() == null) {
                node.setRoot(true);
                node.getLeft().setRoot(false);
                this.rootNode = node;
            }else {
                if (node.isLeft()) {
                    node.getParent().setLeft(node);
                }else {
                    node.getParent().setRight(node);
                }
            }

            if (temp != null) {
                temp.setLeft(false);
                temp.setParent(node.getLeft());
            }
        }
    }

    // trun right
    // node is the pivot
    private void turnRight(TreeNode<V> node) throws CanNotTurnRight {
        TreeNode<V> temp;
        if (node == null || node.getParent() == null) {
            throw new CanNotTurnRight("you cannot turn right because short of valid treenode");
        }else {
            temp = node.getRight();

            node.setRight(node.getParent());
            node.setParent(node.getRight().getParent());
            node.setLeft(node.getRight().isLeft());


            node.getRight().setParent(node);
            node.getRight().setLeft(false);
            node.getRight().setLeft(temp);

            // 如果旋转后支点变成了根节点,那么需要修改它的属性和原根节点的属性
            if (node.getParent() == null) {
                node.setRoot(true);
                node.getRight().setRoot(false);
                this.rootNode = node;
            }else {
                // 如果旋转后支点不是根节点,那么还需要将支点的父节点的左子节点或右子节点改为本支点
                if (node.isLeft()) {
                    node.getParent().setLeft(node);
                }else {
                    node.getParent().setRight(node);
                }
            }

            if (temp != null) {
                temp.setLeft(true);
                temp.setParent(node.getRight());
            }
        }
    }

    /**
     * 输出整棵树
     * @param node
     * @param number
     */
    public void printLikeTree(TreeNode<V> node, int number) throws TreeIsNotValidException {
        if (node == null) {
            return;
        }

        for (int i = 1; i <= number; i++) {
            System.out.print("------|");
        }
        System.out.format((node.isLeft() ? "左" : "右") + (node.isRed() ? "红" : "黑") + "%-4d\n", node.getKey());
        printLikeTree(node.getLeft(), ++number);
        number--;
        printLikeTree(node.getRight(), ++number);
        number--;
    }

    public TreeNode<V> getRootNode() {
        return rootNode;
    }

    public void delete(int key) throws CanNotDeleteNode, TreeIsNotValidException, CanNotTurnLeft, CanNotTurnRight {
        TreeNode<V> currentNode = find(key, rootNode);

        // 如果不存在
        if (currentNode == null) {
            return;
        }
        // 情况1 红色
        if (currentNode.isRed()) {
            // 情况1.1 没有子节点
            if (currentNode.getRight() == null && currentNode.getLeft() == null) {
                deleteSelf(currentNode);
            }
            // 情况1.3 有两个子节点
            else if (currentNode.getRight() != null && currentNode.getLeft() != null) {
                TreeNode<V> oldNode = currentNode;
                currentNode = findNext(currentNode);
                delete(currentNode.getKey());
                oldNode.setKey(currentNode.getKey());
            }
            // 情况1.2 有一个子节点
            else {
                throw new TreeIsNotValidException("红色节点不可能只要一个子节点,当前节点的key为: " + currentNode.getKey());
            }
        }
        // 情况2 黑色
        else {
            // 情况2.1 没有子节点
            if (currentNode.getRight() == null && currentNode.getLeft() == null) {
                // 如果是根节点
                if (currentNode.isRoot()) {
                    rootNode = null;
                    return;
                }
                deleteNoneChildBlack(currentNode);
            }
            // 情况2.3 有两个子节点
            else if (currentNode.getRight() != null && currentNode.getLeft() != null) {
                TreeNode<V> oldNode = currentNode;
                currentNode = findNext(currentNode);
                delete(currentNode.getKey());
                oldNode.setKey(currentNode.getKey());
            }
            //情况2.2 有一个子节点
            else {
                deleteOneChildBlack(currentNode);
            }
        }
    }

    // 删除当前节点
    private boolean deleteSelf(TreeNode<V> node) throws CanNotDeleteNode {
        boolean isSuccess = false;
        if (node.getParent() == null) {
            throw new CanNotDeleteNode("this node ha
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值