文章目录

  • 代码实现
    • 节点实现类
    • 红黑树实现
  • 单元测试

代码实现

节点实现类

package csdn.dreamzuora.tree;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/19 13:30*/
public interface Node {}
package csdn.dreamzuora.tree;import java.io.Serializable;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/19 13:27*/
public abstract class AbstractNode<T, E> implements Node, Serializable {private static final long serialVersionUID = -2321782309212147194L;/*** 数据域*/T data;/*** 左孩子*/E left;/*** 右孩子*/E right;public AbstractNode() {}public AbstractNode(T data) {this.data = data;}public T getData() {return data;}public void setData(T data) {this.data = data;}public E getLeft() {return left;}public void setLeft(E left) {this.left = left;}public E getRight() {return right;}public void setRight(E right) {this.right = right;}
}
package csdn.dreamzuora.tree;/*** Title: 红黑树节点* Description:** @version 1.0* @author: weijie* @date: 2020/10/21 14:36*/
public class RedBlackNode extends AbstractNode<Integer, RedBlackNode>  {/*** 红黑树节点颜色标记*/boolean isBlack;/*** 红黑树父亲节点*/RedBlackNode parent;public RedBlackNode(Integer data) {super(data);//默认为红色this.isBlack = false;}public boolean isBlack() {return isBlack;}public void setBlack(boolean black) {isBlack = black;}public RedBlackNode getParent() {return parent;}public void setParent(RedBlackNode parent) {this.parent = parent;}@Overridepublic String toString() {return "RedBlackNode{" +"isBlack=" + isBlack +", data=" + data +'}';}
}

红黑树实现

package csdn.dreamzuora.tree;import java.util.List;/*** Title: 树接口* Description:** @version 1.0* @author: weijie* @date: 2020/10/16 14:56*/
public interface Tree<T,E> {/*** 构建树* @param dataList*/void createTree(List<T> dataList);/*** 添加节点* @param data*/E addNode(E tree, T data);/*** 删除节点* @param tree* @param node*/void deleteNode(E tree, E node);/*** 前序遍历:根节点->左节点->右节点*/void preOrder(List<T> list, E node);/*** 中序遍历:左节点->根节点->右节点* @return*/void inOrder(List<T> list, E node);/*** 后序遍历:左节点->右节点->根节点*/void laOrder(List<T> list, E node);/*** 广度优先遍历:层序遍历* @param list* @param node*/void bfs(List<T> list, E node);}
package csdn.dreamzuora.tree;import java.io.Serializable;
import java.util.List;/*** Title: 二叉树抽象类* Description:** @version 1.0* @author: weijie* @date: 2020/10/16 14:57*/
public abstract class AbstractTree<T, E> implements Tree<T, E>, Serializable {private static final long serialVersionUID = -8046156919125106629L;/*** 根节点*/E root;@Overridepublic void createTree(List<T> dataList) {for (T data : dataList){addNode(root, data);}}void addNode(T data){};}
package csdn.dreamzuora.tree;import java.util.LinkedList;
import java.util.List;/*** Title: 红黑树* Description:* 规则:* 1.每个节点不是红色就是黑色* 2.每个根节点是黑色* 3.每个叶子节点就是黑色的空节点* 4.如果一个节点是红色的,则它的子节点必须是黑色的(父子不能同为红)* 5.平衡的关键字:从任一节点到其每个叶子的所有路径都包含相同的黑色的节点* 6.新插入节点默认为红色,插入后需要校验红黑树是否符合规则,不符合则需要进行平衡** 再平衡涉及到:左旋、右旋、颜色反转** 红黑树插入分为五种情况:** 1.新节点(A)位于树根,没有父节点*  直接让新节点变成黑色,规则二得到满足,同时,黑色的根节点使得每条路径上的黑色节点数目都增加1,所以*  并没有打破规则5*     A(红)  ->   A(黑)*   1  2        1  2*** 2.新节点(B)的父节点是黑色*   新插入的红色结点B并没有打破红黑树的规则,所以不需要做任何调整*          A(黑)*       B(红)  3*      1  2*** 3.新节点(D)的父节点和叔叔节点都是红色*            A(黑)               A(黑)                   A(红)*       B(红)    C(红)  ->   B(黑)    C(红)  -> ... ->B(黑)   c(黑)*      D(红) 3  4  5        D(红)                   D(红)*     1  2*经过上面的调整,这一局部重新符合了红黑树的规则* 4.新节点(D)的父节点是红色,叔叔节点是黑色或者没有叔叔,且新节点是父节点的右孩子,父节点(B)是祖父节点的左孩子* 我们以节点B为轴,做一次左旋,使得节点D成为父节点,原来的父节点B成为D的左孩子*       A(黑)                 A(黑)*    B(红)   C(黑)  ->   D(红)   C(黑)*   1  D(红) 4  5      B(红) 3  4  5*     2  3           1  2** 5.新节点(D)的父节点是红色,叔叔节点是黑色或者没有叔叔,且新节点是父节点的左孩子,父节点(B)*  是祖父节点的左孩子*  我们以节点A为抽,做一次右旋转,使得节点B成为祖父节点,节点A成为节点B的右孩子*         A(黑)                 B(红)                   B(黑)*      B(红)  C(黑)  ->      D(红)  A(黑)     ->    D(红)   A(红)*    D  3   4   5         1    2  3  C(黑)        1   2  3   C(黑)*  1  2                             4  5                    4  5** 颜色反转:* 如果当前节点、父节点、叔叔节点同为红色,这种情况违反了红黑树的规则,需求将红色向祖辈上传,* 父节点和叔叔节点变为黑色,爷爷节点变为黑->红色** 左旋:逆时针旋转红黑树的两个节点,使得父节点被自己的右孩子取代,而自己成为自己的左孩子*** 右旋:顺时针旋转红黑树的两个节点,使得父节点被自己的左孩子取代,而自己成为自己的右孩子** 时间负责度:logn* @version 1.0* @author: weijie* @date: 2020/10/19 17:39*/
public class RedBlackTree extends AbstractTree<Integer, RedBlackNode> {@Overridepublic void createTree(List<Integer> dataList) {for (Integer data : dataList){addNode(data);}}@Overridepublic void addNode(Integer data) {RedBlackNode node = new RedBlackNode(data);if (root == null){//根为黑色node.setBlack(true);root = node;return ;}RedBlackNode parent = root;RedBlackNode son = null;/*** 判断新节点是放在左子树还是右子树*/if (data <= parent.getData()){son = parent.getLeft();}else {son = parent.getRight();}/*** 对树深度遍历,寻找新节点存放的位置*/while (son != null){parent = son;if (data <= parent.getData()){son = parent.getLeft();}else {son = parent.getRight();}}/*** 节点插入*/if (data <= parent.getData()){parent.setLeft(node);}else {parent.setRight(node);}node.setParent(parent);/*** 自平衡*/balance(node);}@Overridepublic RedBlackNode addNode(RedBlackNode tree, Integer data) {return null;}/*** 自平衡* @param node*/private void balance(RedBlackNode node){RedBlackNode father;RedBlackNode grandFather;/*** 获取父节点并判断父节点是否为红色节点,规则:父子不同为红*/while ((father = node.getParent()) != null && father.isBlack() == false){//获取祖父节点grandFather = father.getParent();//判断父节点在祖先节点存在的位置if (grandFather.getLeft() == father){//叔叔节点RedBlackNode uncle = grandFather.getRight();//如果父亲、叔叔节点存在且都为红,则父亲、叔叔节点变为黑色if (uncle != null && uncle.isBlack() == false){father.setBlack(true);uncle.setBlack(true);grandFather.setBlack(false);//接着对祖先节点进行颜色反转node = grandFather;continue;}/*** 如果没有触发颜色反转,需要进行左旋、右旋操作*/if (node == father.getRight()){//左旋leftRotate(father);RedBlackNode temp = node;node = father;father = temp;}father.setBlack(true);grandFather.setBlack(false);rightRotate(grandFather);}else {RedBlackNode uncle = grandFather.getLeft();if (uncle != null && uncle.isBlack() == false){father.setBlack(true);uncle.setBlack(true);grandFather.setBlack(false);node = grandFather;continue;}if (node == father.getLeft()){rightRotate(father);RedBlackNode temp = node;node = father;father = temp;}father.setBlack(true);grandFather.setBlack(false);leftRotate(grandFather);}}root.setBlack(true);}public void leftRotate(RedBlackNode node){RedBlackNode right = node.getRight();RedBlackNode parent = node.getParent();if (parent == null){root = right;right.setParent(null);}else {if (parent.getLeft() != null && parent.getLeft() == node){parent.setLeft(right);}else {parent.setRight(right);}right.setParent(parent);}node.setParent(right);node.setRight(right.getLeft());if (right.getLeft() != null){right.getLeft().setParent(node);}right.setLeft(node);}private void rightRotate(RedBlackNode node){RedBlackNode left = node.getLeft();RedBlackNode parent = node.getParent();if (parent == null){root = left;left.setParent(null);}else {if (parent.getLeft() != null && parent.getLeft() == node){parent.setLeft(left);}else {parent.setRight(left);}left.setParent(left);}node.setParent(left);node.setLeft(left.getRight());if (left.getRight() != null){left.getRight().setParent(node);}left.setRight(node);}@Overridepublic void deleteNode(RedBlackNode root, RedBlackNode node) {}@Overridepublic void preOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//叶子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}showList.add(node.getData());//递归 左孩子preOrder(showList, node.getLeft());//递归 右孩子preOrder(showList, node.getRight());}@Overridepublic void inOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//叶子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}//递归 左孩子inOrder(showList, node.getLeft());showList.add(node.getData());//递归 右孩子inOrder(showList, node.getRight());}@Overridepublic void laOrder(List<Integer> showList, RedBlackNode node) {if(node == null) {return ;}//叶子if(node.getLeft() == null && node.getRight()==null){showList.add(node.getData());return ;}//递归 左孩子laOrder(showList, node.getLeft());//递归 右孩子laOrder(showList, node.getRight());showList.add(node.getData());}@Overridepublic void bfs(List<Integer> list, RedBlackNode node) {if (node == null){return;}LinkedList<RedBlackNode> queue = new LinkedList<>();queue.offer(node);while (!queue.isEmpty()){RedBlackNode child = queue.poll();list.add(child.data);if (child.left != null){queue.offer(child.left);}if (child.right != null){queue.offer(child.right);}}}
}

单元测试

package csdn.dreamzuora.tree;import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import static org.junit.Assert.*;/*** Title:* Description:** @version 1.0* @author: weijie* @date: 2020/10/22 14:31*/
public class RedBlackTreeTest {RedBlackTree RBtree = new RedBlackTree();@Beforepublic void init() {List<Integer> list = Arrays.asList(10, 5, 9, 3, 6, 7, 19, 32, 24, 17);RBtree.createTree(list);}@Testpublic void addNode(){}@Testpublic void deleteNode() {}@Testpublic void preOrder() {List<Integer> actualList = new ArrayList<>();RBtree.preOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(9, 5, 3, 6, 7, 19, 10, 17, 32, 24);Assertions.assertEquals(expectList, actualList);}@Testpublic void inOrder() {List<Integer> actualList = new ArrayList<>();RBtree.inOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(3, 5, 6, 7, 9, 10, 17, 19, 24, 32);Assertions.assertEquals(expectList, actualList);}@Testpublic void laOrder() {List<Integer> actualList = new ArrayList<>();RBtree.laOrder(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(3, 7, 6, 5, 17, 10, 24, 32, 19, 9);Assertions.assertEquals(expectList, actualList);}@Testpublic void bfs() {List<Integer> actualList = new ArrayList<>();RBtree.bfs(actualList, RBtree.root);List<Integer> expectList = Arrays.asList(9, 5, 19, 3, 6, 10, 32, 7, 17, 24);Assertions.assertEquals(expectList, actualList);}@Testpublic void leftRotate(){}@Testpublic void rightRotate(){RedBlackNode node5 = new RedBlackNode(5);RedBlackNode node3 = new RedBlackNode(3);RedBlackNode node8 = new RedBlackNode(8);RedBlackNode node7 = new RedBlackNode(7);RedBlackNode node9 = new RedBlackNode(9);RBtree.root = node5;RBtree.root.left = node3;node8.left = node7;node8.right = node9;RBtree.root.right = node8;RBtree.leftRotate(RBtree.root);}
}

红黑树 java代码实现相关推荐

  1. 红黑树-Java实现

    目录 一.定义 二.插入 三.删除 四.全部代码 五.颜色效果 一.定义 红黑树是特殊的平衡二叉树,具有以下特性: 1.根节点的颜色是黑色 2.节点颜色要么是黑色.要么是红色 3.如果一个节点的颜色是 ...

  2. 红黑树+java+删除_红黑树深入剖析及Java实现

    红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小, ...

  3. 数据结构之 红黑树(左倾红黑树) java实现

    为啥要有红黑树 上一章我们聊到了二叉查找树数,但是二叉查找树在 插入的时候 如果 递增插入或者递减插入 ,就会导致这个棵树 单边倾斜,或者说单边增长从而退化成链表而影响查询效率,如下图 从而引进了红黑 ...

  4. 快手高级Java四轮面试题:设计模式+红黑树+Java锁+Redis等

    快手Java一面(一个小时十分钟) 1.自我介绍 2.说说B+树和B树的区别,优缺点等? 3聊聊Spring,主要IOC等等 4多线程JUC包下的一些常见的类,比如CountDownLatch.Sem ...

  5. 自顶向下红黑树java,【CPP】各种各样的树(9)——自顶向下的红黑树

    当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 本以为春节后马上就能写完这些树了,结果没想到一拖再拖居然拖到了开学前,很真实.红黑树还是蛮难的,写着写着才意识到应该先搞完B树然后再写2-3 ...

  6. 最新快手面试题(含总结):设计模式+红黑树+Java锁+Redis等

    每年春节后两个月都是招聘高峰期,很多想换工作的职场人士都会选择在此时换一份工作,毕竟一年之计在于春,对于公司和个人而言都是一个新的开始. 大家在春节长假身心得到放松后,准备摩拳擦掌的找工作了,不过大部 ...

  7. 算法之红黑树/JAVA

    文章目录 1.2 红黑树 1.2.1 2-3查找树 1.2.2 红黑树 结点定义 旋转操作 插入 put()实现 红黑树的性质 1.2 红黑树 1.2.1 2-3查找树 因为二叉查找树是不平衡的,如果 ...

  8. 理解红黑树及代码实现

    1.红黑树定义 红黑树是一颗 红-黑的平衡二叉树,它具有二叉树的所有特性,是一颗自平衡的排序二叉树.(树中任何节点值都大于左子节点的值,而且都小于右子节点的值),其检索效率高,它是一颗空树或它的左右两 ...

  9. 红黑树java源代码分析_JAVA 红黑树源码

    class RBTree>{ private static final String RedColor = "red"; private static final Strin ...

最新文章

  1. 二叉树(中序遍历)非递归
  2. 定义范围中的备选方案生成、横向思维、创建WBS、工作包定义、WBS、确认范围过程和实施质量过程的关系、联合应用设计和质量功能展开QFD
  3. spring mvc学习(21):testparam请求参数和请求头表达式
  4. 数字签名,数字证书,证书链原理
  5. [HNOI2013]比赛 搜索
  6. 吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
  7. 职称评审英语计算机不作要求,安徽:基层专业技术人员评职称外语计算机不作要求...
  8. Win10+Pytorch0.4.1版本+cuda一键安装
  9. 华为硬件工程师社招机考题库_华为硬件工程师笔试题
  10. C语言必会100题(2)。用*号输出字母C的图案/输出特殊图案/输出9*9口诀/输出国际象棋棋盘/打印楼梯,同时在楼梯上方打印两个笑脸
  11. react从入门到入魔
  12. 3.注册后台处理逻辑编写
  13. 自己实现SDIO wifi Marvell8801/Marvell88w8801驱动 介绍(一) ---- 芯片介绍
  14. obj转stl_STL转STP的方法视频教程,OBJ格式转STP或者IGS开模具格式的过程,STL转STP软件介绍...
  15. 迅捷画图中套用流程图模板编辑方法介绍
  16. 售前工程师——PaaS
  17. PJzhang:关闭wps小广告和快速关闭445端口
  18. 微信小程序突然多了好多动态_让微信小程序的登陆页面有云朵悬浮的动态效果...
  19. [附源码]java毕业设计房屋中介管理系统
  20. Linux个人防火墙设计

热门文章

  1. Git仓库迁移,包括所有的分支、标签、日志
  2. PKU 学生反馈 2009 - 4
  3. java url authority,Java如何解析url,包括自定义schema的url
  4. python总结教程_python基础教程总结10——文件
  5. git灰度发布版本_Git发布2.30版本
  6. vlan为什么能隔离广播域_路由交换技术-VLAN原理及配置
  7. windows的python切换环境_Windows下的python虚拟环境设置
  8. python适用的操作系统是_操作系统先来先服务python
  9. 电脑入门完全自学手册_电气自动化自学宝典——看过人人都是工程师
  10. 【LeetCode笔记】142. 环形链表 II(Java、快慢指针)