广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >java实现红黑树的代码怎么写
  • 324
分享到

java实现红黑树的代码怎么写

2024-04-02 19:04:59 324人浏览 八月长安
摘要

本篇内容介绍了“java实现红黑树的代码怎么写”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 红黑树ja

本篇内容介绍了“java实现红黑树的代码怎么写”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

红黑树java代码实现

package tree;

import jdk.nashorn.internal.ir.Callnode;

import java.util.Random;


public class RBTree {
    private RBTree.Node root = null;

    private enum Color {RED, BLACK}

    private enum Child {LEFT, RIGHT}

    private class Node {
        private Integer key;    //key
        private Object data;    //value
        private Node leftChild;   //左子节点
        private Node rightChild;  //右子节点
        private Node parent;  //父节点
        private Color color;   //红黑标示

        private Node() {
        }

        Node(Object key, Object data, Color color) {
            this.key = (Integer) key;
            this.data = data;
            this.color = color;
        }

        public Color getColor() {
            return color;
        }

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

        boolean isRed() {
            if (this.color.equals(Color.RED))
                return true;
            return false;
        }
    }

    
    boolean insertNode(Integer key, Object value) {
        return insertNode(root, key, value, null, Child.LEFT);
    }

    private boolean insertNode(Node node, Integer key, Object value, Node preNode, Child child) {
        if (node == null) {
            node = new Node(key, value, Color.RED);
            if (preNode == null) {  //父节点为空,将node设为根节点
                root = node;
            } else {
                if (child.equals(Child.LEFT)) {
                    preNode.leftChild = node;
                } else {
                    preNode.rightChild = node;
                }
                node.parent = preNode;
            }

            //通过RB_INSERT_FIXUP对红黑树的结点进行颜色修改以及旋转,让树仍然是一颗红黑树
            RB_INSERT_FIXUP(node);
            return true;
        } else {
            if (key.compareTo(node.key) == 0) {
                //root = node;
                return false;
            } else if (key.compareTo(node.key) < 0) {
                if (!insertNode(node.leftChild, key, value, node, Child.LEFT)) {
                    return false;
                }
            } else {
                if (!insertNode(node.rightChild, key, value, node, Child.RIGHT)) {
                    return false;
                }
            }
            return true;
        }
    }

    
    private void RB_INSERT_FIXUP(Node node) {
        Node pNode = node.parent;
        if (node == root) { //插入结点为跟节点,直接改变颜色
            node.setColor(Color.BLACK);
            return;
        }
        if (node == null || pNode.color.equals(Color.BLACK)) {    //插入结点的父结点为黑结点,由于插入的结点是红色的,并不会影响红黑树的平衡,直接插入即可,无需做自平衡。
            return;
        } else {    //情景4:插入结点的父结点为红结点
            Node graNode = node.parent.parent;
            if (pNode == graNode.leftChild) {  //父节点是祖父节点的左子节点
                if (graNode.rightChild != null && graNode.rightChild.isRed()) { //情景4.1:叔叔结点存在并且为红结点
                    
                    pNode.setColor(Color.BLACK);
                    graNode.rightChild.setColor(Color.BLACK);
                    graNode.setColor(Color.RED);
                    RB_INSERT_FIXUP(graNode);
                } else { //情景4.2:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点
                    if (node == pNode.leftChild) {//情景4.2.1 插入结点是其父结点的左子结点
                        
                        pNode.setColor(Color.BLACK);
                        graNode.setColor(Color.RED);
                        RRotate(graNode);
                    } else {    //情景4.2.2 插入结点是其父结点的右子结点
                        
                        LRotate(pNode);
                        RB_INSERT_FIXUP(pNode);
                    }

                }
            } else { //4.3 父节点是祖父节点的右子节点
                if (graNode.leftChild != null && graNode.leftChild.isRed()) { //情景4.3:叔叔结点存在并且为红结点+
                    
                    pNode.setColor(Color.BLACK);
                    graNode.leftChild.setColor(Color.BLACK);
                    graNode.setColor(Color.RED);
                    RB_INSERT_FIXUP(graNode);
                } else { //情景4.3.1:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点
                    if (node == pNode.rightChild) {//情景4.3.1:插入结点是其父结点的右子结点
                        
                        pNode.setColor(Color.BLACK);
                        graNode.setColor(Color.RED);
                        LRotate(graNode);
                    } else {    //情景4.3.2 插入结点是其父结点的右子结点
                        
                        RRotate(pNode);
                        RB_INSERT_FIXUP(pNode);
                    }
                }
            }
        }
    }

    
    private void RRotate(Node T) {
        Node lc = T.leftChild;
        T.leftChild = lc.rightChild;
        if (T.leftChild != null) {
            T.leftChild.parent = T;
        }
        lc.rightChild = T;
        returnPNode(T, lc);
    }

    private Node returnPNode(Node T, Node node) {
        if (T == root) {
            root = node;
        } else if (T.parent.leftChild == T) {
            T.parent.leftChild = node;
        } else {
            T.parent.rightChild = node;
        }
        node.parent = T.parent;
        T.parent = node;
        return node;
    }

    
    private void LRotate(Node T) {
        Node rc = T.rightChild;
        T.rightChild = rc.leftChild;
        if (T.rightChild != null) {

            T.rightChild.parent = T;
        }
        rc.leftChild = T;
        returnPNode(T, rc);
    }

    
    public void ldrTraversal() {
        ldrTraversal(root);
    }

    
    private void ldrTraversal(Node node) {
        if (node != null) {
            ldrTraversal(node.leftChild);
            System.out.print(node.key + ":" + node.color + ";");
            //System.out.print("key:" + node.key + "-value" + node.data + ":" + node.color + ";");
            ldrTraversal(node.rightChild);
        }

    }

    
    public void dlrTraversal() {
        dlrTraversal(root);
    }

    
    private void dlrTraversal(Node node) {
        if (node != null) {
            System.out.print(node.key + ":" + node.color + ";");
            dlrTraversal(node.leftChild);
            dlrTraversal(node.rightChild);
        }

    }

    
    public void lrdTraversal() {
        lrdTraversal(root);
    }

    
    private void lrdTraversal(Node node) {
        if (node != null) {
            lrdTraversal(node.leftChild);
            lrdTraversal(node.rightChild);
            System.out.print("key:" + node.key + "-value" + node.data + ":" + node.color + ";");
        }

    }

    
    public Object search(Integer key) {
        if (this.root != null) {
            return searchNode(key, root).data;
        }
        return null;
    }

    
    public boolean removen(Integer key) {
        if (this.root != null) {
            Node node = searchNode(key, root);
            if (node == null) {
                return false;
            }
            removenNode(node);
            return true;
        }
        return false;
    }

    
    private void removenNode(Node node) {
        if (node == null) {
            return;
        }
        if (node.leftChild == null && node.rightChild == null) {    //情景1:若删除结点无子结点,直接删除。
            changeNode(node, null);
        } else if (node.leftChild != null && node.rightChild != null) { //情景3:若删除结点有两个子结点,用后继结点(大于删除结点的最小结点)替换删除结点。
            Node rNode = node.rightChild;
            while (rNode.leftChild != null) {   //找到后继结点
                rNode = rNode.leftChild;
            }
            //  交换位子
            
            changeNode(node, rNode);    //用后继节点替换要删除节点
        } else { //情景2:若删除结点只有一个子结点,用子结点替换删除结点。
            if (node.leftChild != null) {
                changeNode(node, node.leftChild);
            } else {
                changeNode(node, node.rightChild);
            }
        }
    }

    
    private void changeNode(Node delNode, Node fixupNode) {
        RB_DELETE_FIXUP(fixupNode);

        if (fixupNode == null) {
            if (delNode.parent.leftChild == delNode) {
                delNode.parent.leftChild = null;
            } else {
                delNode.parent.rightChild = null;
            }
            return;
        }

        Object data = delNode.data;
        Color color = delNode.color;
        Integer key = delNode.key;
        if (delNode == root) {  // 交换时如果删除节点是根节点,颜色直接改成黑色
            delNode.setColor(Color.BLACK);
        } else {
            delNode.color = fixupNode.color;
        }
        delNode.key = fixupNode.key;
        delNode.data = fixupNode.data;
        fixupNode.key = key;
        fixupNode.data = data;
        fixupNode.color = color;

        removenNode(fixupNode);
    }

    public Node searchNode(Integer key, Node node) {
        if (node == null)
            return null;
        if (node.key.compareTo(key) == 0) {
            return node;
        } else if (key.compareTo(node.key) < 0) {
            if (node.leftChild != null) {
                return searchNode(key, node.leftChild);
            }
            return null;
        } else {
            if (node.rightChild != null) {
                return searchNode(key, node.rightChild);
            }
            return null;
        }
    }

    private void RB_DELETE_FIXUP(Node fixupNode) {
        if (fixupNode == null || fixupNode.isRed()) {    //情景1:替换结点是红色结点
            
            return;
        } else {  //情景2:替换结点是黑结点
            Node bNode = fixupNode.parent.rightChild;
            if (fixupNode == fixupNode.parent.leftChild) { //情景2.1:替换结点是其父结点的左子结点
                //情景2.1.1:替换结点的兄弟结点是红结点
                if (bNode.isRed()) {
                    bNode.setColor(Color.BLACK);
                    fixupNode.parent.setColor(Color.RED);
                    RRotate(fixupNode.parent);
                    RB_DELETE_FIXUP(fixupNode);
                } else {  //情景2.1.2: 替换结点的兄弟结点是黑结点
                    //情景2.1.2.1:替换结点的兄弟结点的右子结点是红结点,左子结点任意颜色
                    if (bNode.rightChild != null && bNode.rightChild.isRed()) {
                        
                        bNode.color = fixupNode.parent.color;
                        fixupNode.parent.setColor(Color.BLACK);
                        bNode.rightChild.setColor(Color.RED);
                        LRotate(fixupNode.parent);
                    } else if (bNode.leftChild != null && bNode.leftChild.isRed()) {
                        //情景2.1.2.2:替换结点的兄弟结点的右子结点为黑结点,左子结点为红结点
                        
                        bNode.setColor(Color.RED);
                        bNode.leftChild.setColor(Color.BLACK);
                        RRotate(bNode);
                        RB_DELETE_FIXUP(fixupNode);
                    } else {//删除情景2.1.2.3: 替换结点的兄弟结点的子结点都为黑结点
                        
                        bNode.setColor(Color.RED);
                        RB_DELETE_FIXUP(fixupNode.parent);
                    }

                }
            } else {
                //删除情景2.2: 替换结点是其父结点的右子结点
                //删除情景2.2.1: 替换结点的兄弟结点是红结点
                if (bNode.isRed()) {
                    
                    bNode.setColor(Color.BLACK);
                    fixupNode.parent.setColor(Color.RED);
                    LRotate(fixupNode.parent);
                    RB_DELETE_FIXUP(fixupNode);
                } else { //删除情景2.2.2: 替换结点的兄弟结点是黑结点
                    //删除情景2.2.2.1: 替换结点的兄弟结点的左子结点是红结点,右子结点任意颜色
                    if (bNode.leftChild != null && bNode.leftChild.isRed()) {
                        
                        bNode.color = fixupNode.parent.color;
                        fixupNode.parent.setColor(Color.BLACK);
                        bNode.leftChild.setColor(Color.BLACK);
                        RRotate(fixupNode.parent);
                    } else if (bNode.rightChild != null && bNode.rightChild.isRed()) {//删除情景2.2.2.2: 替换结点的兄弟结点的左子结点为黑结点,右子结点为红结点
                        
                        bNode.setColor(Color.RED);
                        bNode.rightChild.setColor(Color.BLACK);
                        LRotate(bNode);
                        RB_DELETE_FIXUP(fixupNode);
                    } else {//删除情景2.2.2.3:替换结点的兄弟结点的子结点都为黑结点
                        
                        bNode.setColor(Color.RED);
                        RB_DELETE_FIXUP(fixupNode.parent);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        //int[] data={8,6,4};
        //int[] data={8,6,9,5,7,3};
        //int[] data={8,6,7};
        //int[] data={8,5,9,4,6,7};
        //int[] data={8,5,9,4,7,6};
        //int[] data = {8, 5, 9, 7, 6};
        //Object[] data = new Object[100];
        //Object[] data = {2, 4, 15, 11, 19, 3, "F", "G", "B", "A", "D", "C", "E", new Person("小王", 22)};
        
        RBTree rbt = new RBTree();
        int[] data = {2, 4, 15, 11, 19, 3, 12, 14, 16, 9, 13, 17, 7, 8, 5, 1, 18, 6};
        for (int i = 0; i < data.length; i++) {
            if (data[i] == 9) {
                System.out.println();
            }
            System.out.println(data[i]);
            rbt.insertNode(data[i], data[i]);
            rbt.dlrTraversal();
            System.out.println("\n" + rbt.root.data);
        }
        rbt.removen(6);
        
        rbt.ldrTraversal();
        System.out.println("\n" + rbt.root.data);
        rbt.dlrTraversal();
        //System.out.println("\n" + rbt.search("0"));
    }
}

“java实现红黑树的代码怎么写”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: java实现红黑树的代码怎么写

本文链接: https://www.lsjlt.com/news/90303.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java实现红黑树的代码怎么写
    本篇内容介绍了“java实现红黑树的代码怎么写”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 红黑树ja...
    99+
    2022-10-19
  • C语言实现手写红黑树的示例代码
    目录前沿红黑树代码测试前沿 写C的红黑树前建议先看我博客这篇文章Java-红黑树 主要看原理 红黑树代码 #ifndef STUDY_RBTREE_H #define ...
    99+
    2022-11-13
  • C++实现红黑树应用实例代码
    红黑树的应用: 1、利用key_value对,快速查找,O(logn) socket与客户端id之间,形成映射关系(socket, id) 内存分配管理 ...
    99+
    2022-11-12
  • C语言实现红黑树详细步骤+代码
    目录红黑树的概念红黑树的性质红黑树的定义与树结构插入新增结点插入后维护红黑树性质的主逻辑拆解讨论:旋转验证红黑树与AVl树的比较红黑树的应用总结红黑树的概念 红黑树,是一种二叉搜索树...
    99+
    2022-11-12
  • C语言实现手写Map(数组+链表+红黑树)的示例代码
    目录要求结构红黑树和链表转换策略hash使用要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备...
    99+
    2022-11-13
  • Java实现二叉树的代码怎么写
    本篇内容主要讲解“Java实现二叉树的代码怎么写”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java实现二叉树的代码怎么写”吧!以此图为例,完整代码如下://基础二叉树实现//使用左右孩子表示...
    99+
    2023-06-29
  • Java实现红黑树(平衡二叉树)的详细过程
    目录前言红黑二叉查找树2-3树2-3树的插入操作实现红黑二叉树结尾前言 在实现红黑树之前,我们先来了解一下符号表。 符号表的描述借鉴了Algorithms第四版,详情在:https...
    99+
    2022-11-12
  • 红黑树的实现原理是什么
    本篇文章给大家分享的是有关红黑树的实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、摘要平衡二叉查找树是一个高度平衡的二叉树,也...
    99+
    2022-10-19
  • Java实现树形结构的代码怎么写
    本篇内容介绍了“Java实现树形结构的代码怎么写”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!数据库表结构实现思路拿到有父子节点的集合数据遍...
    99+
    2023-06-30
  • Java数据结构之红黑树的原理及实现
    目录为什么要有红黑树这种数据结构红黑树的简介红黑树的基本操作之旋转红黑树之添加元素红黑树之删除结点删除结点没有儿子的情况删除结点仅有一个儿子结点的情况删除结点有两个儿子结点红黑树动态...
    99+
    2022-11-13
  • C++ RBTree红黑树的性质与实现方法是什么
    这篇文章主要讲解了“C++ RBTree红黑树的性质与实现方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++ RBTree红黑树的性质与实现方法是什么”吧!一...
    99+
    2023-07-05
  • 基于红黑树插入操作原理及java实现的示例分析
    这篇文章主要介绍基于红黑树插入操作原理及java实现的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!红黑树是一种二叉平衡查找树,每个结点上有一个存储位来表示结点的颜色,可以是RED或BLACK。红黑树具有以下...
    99+
    2023-05-30
    java
  • Java实现Treap树的示例代码
    目录Treap树数据结构遍历查询增加删除完整代码Treap树 Treap树是平衡二叉搜索树的一种实现方式,但它不是完全平衡的。平衡二叉搜索树的实现方式还有AVL树、红黑树、替罪羊树、...
    99+
    2022-11-13
  • java实现时钟代码怎么写
    以下是一个简单的Java代码示例,用于实现一个时钟:```javaimport java.time.LocalTime;import...
    99+
    2023-08-29
    java
  • java实现线程代码怎么写
    在Java中,可以使用以下两种方式实现线程: 继承Thread类 public class MyThread extends Th...
    99+
    2023-10-28
    java
  • JAVA实现红包分发的示例代码
    大体思路 如果发总金额为 m的 n 个红包,先用一个长度为 n的临时数组 a 存放 n个随机双精度小数 ,然后用  sum表示数组 a 的和,每个红包的金额 代码 ...
    99+
    2022-11-12
  • php代码怎么实现红包功能
    本文操作环境:Windows7系统、PHP7.1版、DELL G3电脑php代码怎么实现红包功能PHP 红包功能代码前段时间被问这个问题,最近有空就写写啦,还是挺有趣的首先做下抢红包方法分类:对于发红包的人来说,一共有大致3类(其他的我暂时...
    99+
    2018-08-18
    php 红包
  • Java实现byte[]转List的代码怎么写
    Java实现byte[]转List的代码怎么写,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。前言其实这个工具是给自己写的,因为自己老是忘记。所以记录一下。Mav...
    99+
    2023-06-29
  • java实现计算器的代码怎么写
    以下是一个简单的Java代码实现计算器的示例:```javaimport java.util.Scanner;public class Calculator {public static void main(String[] args)...
    99+
    2023-08-11
    java
  • 怎么用Unity代码实现红酒识别
    这篇文章主要介绍“怎么用Unity代码实现红酒识别”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用Unity代码实现红酒识别”文章能帮助大家解决问题。接口介绍:识别图像中的红酒标签,返回红酒名称...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作