package com.yeyu.study1.list;/*** 红黑树**  1、构建节点对象结构 定义颜色属性*  2、辅助方法定义:  parentOf(node) isRed(node) , isBlack(node), setRed(node) , inOrderPrint()*  3、左旋方法*  4、右旋方法*  5、定义公开的插入方法*  6、实现内部的插入方法*  7、实现修正插入导致红黑树失衡的方法定义:*** key继承 Comparable用于给K排序*/
public class RbTree<K extends Comparable,V>{private static final boolean RED = true;  //红色private static final boolean BLACK = false; //黑色/** 根节点 */private RBNode root;public RBNode getRoot(){return root;}/*** 获得当前节点的父节点* @param node*/private RBNode parentOf(RBNode node){if(node!=null){return node.parent;}return null;}/*** 节点是否为红色* @param node* @return*/private boolean isRed(RBNode node){if(node!=null){return node.color == RED;}return false;}/*** 节点是否为黑色* @param node* @return*/private boolean isBlack(RBNode node){if(node!=null){return node.color == BLACK;}return false;}/*** 设置节点为红色* @param node*/private void setRed(RBNode node){if(node!=null){node.color = RED;}}/*** 设置节点为黑色* @param node*/private void setBlack(RBNode node){if(node!=null){node.color = BLACK;}}/*** 中序打印二叉树*/public void inOrderPrint(){inOrderPrint(root);}private void inOrderPrint(RBNode node){if(node != null){inOrderPrint(node.left);System.out.println("key:"+node.k + ", value:"+node.v);inOrderPrint(node.right);}}/*** 公开的插入方法* @param key* @param value*/public void put(K key,V value){RBNode node = new RBNode();node.setColor(RED);//新节点都是红色node.setK(hash(key));node.setV(value);put(node);}/*** 参考hashmap 给key做取模运算  可以插入key 为 null* @param key* @return*/static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}/*** 内部的插入方法* @param node*/private void put(RBNode node){//1、查找当前节点的父节点RBNode parent = null;RBNode x = this.root;while (x != null){parent = x;//排序方法 返回 >0 说明 node.k 大于x.k 需要到x的右子树查找//排序方法 返回 =0 说明 node.k 等于x.k 进行value的替换//排序方法 返回 <0 说明 node.k 小于x.k 需要到x的左子树查找int flag = node.k.compareTo(x.k);if(flag>0){x = x.right;}else if(flag==0){x.setV(node.getV());return;}else {x = x.left;}}node.parent = parent;//判断node与parent的key 谁大if(parent!=null){int flag = node.k.compareTo(parent.k);if(flag>0){ //当前node.k比parent的k大,需要把node放入parent的右节点parent.right = node;}else{  //当前node.k比parent的k小,需要把node放入parent的左节点parent.left = node;}}else {this.root = node;}//需要调用修复红黑树平衡方法 检测本次插入是否破坏平衡putFixUp(node);}/*** 修复红黑树方法:* 1、如 红黑树为空树  将根节点变黑* 2、如 插入的节点已存在  不需要处理 直接替换V即可* 3、如 插入的父节点为黑色 , 不需要处理  因为黑色节点没有加深 所以红黑树依旧平衡*** 4、如  插入节点的父节点为红色  需要处理  不能红红相连*      4.1 叔叔节点存在并且为红色 (父-叔 双红)  处理方式:将爸爸叔叔变为黑色,将爷爷染为红色  并且再以爷爷为当前节点进行下一轮处理*      4.2 叔叔节点不存在  或者为黑色  父节点是爷爷节点的左子树*          4.2.1   插入节点为其父节点的左子节点(LL 左左) 将爸爸变为黑色,将爷爷变为红色 然后以爷爷节点右旋,就完成了*          4.2.2   插入节点为其父节点的右子节点(LR 左右) 以爸爸节点进行左旋,得到LL双红(4.2.1)的情景 然后指定爸爸节点进行下一轮处理*      4.3 叔叔节点不存在  或者为黑色  父节点是爷爷节点的右子树*          4.3.1   插入节点为其父节点的右子节点(RR情况) 将爸爸变为黑色,将爷爷变为红色 然后以爷爷节点进行左旋 就可以了*          4.3.2   插入节点为其父节点的左子节点(RL情况) 以爸爸节点进行右旋  得到RR双红情景(4.3.1) 然后指定爸爸节点进行下一轮处理**/private void putFixUp(RBNode node){this.root.setColor(BLACK);  //解决1场景RBNode parent = parentOf(node);  //拿到爸爸节点RBNode gparent = parentOf(parent);  //爷爷节点//4场景: 插入节点的父节点为红色if(parent != null && isRed(parent)){//如果父节点是红色 那么一定存在爷爷节点  因为跟根节点不可能是红色RBNode uncle = null; //叔叔节点if(parent == gparent.left){ //判断父节点是否是爷爷的左节点uncle = gparent.right;//4.1情景:叔叔节点存在并且为红色 (父-叔 双红)  处理方式:将爸爸叔叔变为黑色,将爷爷染为红色  并且再以爷爷为当前节点进行下一轮处理if(uncle!=null && isRed(uncle)){setBlack(parent);setBlack(uncle);setRed(gparent);inOrderPrint(gparent);return;}//4.2场景:叔叔节点不存在或者为黑色if(uncle == null || isBlack(uncle)){//4.2.1   插入节点为其父节点的左子节点(LL 左左) 将爸爸变为黑色,将爷爷变为红色 然后以爷爷节点右旋,就完成了if(node==parent.left){setBlack(parent);setRed(gparent);rightRotate(gparent);return;}//4.2.2   插入节点为其父节点的右子节点(LR 左右)// 以爸爸节点进行左旋,得到LL双红(4.2.1)的情景 然后指定爸爸节点进行下一轮处理if(node==parent.right){leftRotate(parent);putFixUp(parent);return;}}}else{ //父节点为爷爷的右节点uncle = gparent.left;//4.1情景:叔叔节点存在并且为红色 (父-叔 双红)  处理方式:将爸爸叔叔变为黑色,将爷爷染为红色  并且再以爷爷为当前节点进行下一轮处理if(uncle!=null && isRed(uncle)){setBlack(parent);setBlack(uncle);setRed(gparent);putFixUp(gparent);return;}//4.3 叔叔节点不存在  或者为黑色  父节点是爷爷节点的右子树if(uncle==null || isBlack(uncle)){//4.3.1   插入节点为其父节点的右子节点(RR情况) 将爸爸变为黑色,将爷爷变为红色 然后以爷爷节点进行左旋 就可以了if(node==parent.right){setBlack(parent);setRed(gparent);leftRotate(gparent);return;}//4.3.2   插入节点为其父节点的左子节点(RL情况) 以爸爸节点进行右旋  得到RR双红情景(4.3.1) 然后指定爸爸节点进行下一轮处理if(node==parent.left){rightRotate(parent);putFixUp(parent);return;}}}}}/*** 左旋方法* 1、将右子节点的左子节点改为自身的右节点 并将其的父节点改为自身* 2、当自身父节点不为空时,更新原右子节点的父节点为原父节点  并将父节点的字数指向原右子节点 并将自身的父节点只想原右节点*/private void leftRotate(RBNode x){RBNode y  = x.right;  //拿到右子节点x.right = y.left;if(y.left != null){y.left.parent = x;}if(x.parent!=null){y.parent = x.parent;if(x == x.parent.left){x.parent.left = y;}else {x.parent.right = y;}}else {this.root = y;this.root.parent=null;}//更新父节点x.parent = y;y.left = x;}/*** 右旋方法* 和左旋相反的操作* @param x*/private void rightRotate(RBNode x){RBNode y = x.left;x.left = y.right;if(y.right!=null){y.right.parent=x;}if(x.parent!=null){y.parent = x.parent;if(x == x.parent.left){x.parent.left = y;}else {x.parent.right = y;}}else {this.root = y;this.root.parent=null;}x.parent=y;y.right = x;}public static class RBNode<K extends Comparable,V>{private RBNode parent; //父节点private RBNode left; //左节点private RBNode right; //右节点private boolean color; //颜色  红黑private K k;private V v;public RBNode() {}public RBNode getParent() {return parent;}public void setParent(RBNode parent) {this.parent = parent;}public RBNode getLeft() {return left;}public void setLeft(RBNode left) {this.left = left;}public RBNode getRight() {return right;}public void setRight(RBNode right) {this.right = right;}public boolean isColor() {return color;}public void setColor(boolean color) {this.color = color;}public K getK() {return k;}public void setK(K k) {this.k = k;}public V getV() {return v;}public void setV(V v) {this.v = v;}public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K k, V v) {this.parent = parent;this.left = left;this.right = right;this.color = color;this.k = k;this.v = v;}}
}

java实现红黑树 新增节点 左旋右旋 hash取模相关推荐

  1. 红黑二叉树的左旋右旋和变色

    小白解析红黑树的基本 什么是红黑树 变色 右旋 什么是右旋呢? 左旋 什么情况下会左旋 什么是红黑树 这就是一个简单的红黑二叉树 红黑二叉树有以下几条基本的规则: 1. 节点分为红色或者黑色. 2.根 ...

  2. JAVA:红黑树详解

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 本文转载自公众号:乱敲代码 1.定义 红黑树是特殊的二叉查找树,又名R-B树(RED-BLA ...

  3. HashMap 数据结构之红黑树, 红黑树在什么时候左旋 右旋 如何旋转

    树结构是数据结构中最经典最常用的结构之一,也是面试中常问的面试题,最近学习了一下红黑树的知识,记录整理一下 文章目录 一.红黑树的特征 二.变色左旋和右旋 1.变色规则 2.左旋 3.右旋 总结 前言 ...

  4. 红黑树简介及左旋、右旋、变色

    红黑树简介及左旋.右旋.变色 红黑树(Red Black Tree)是一种自平衡二叉搜索树(二叉查找树),是一种特殊的二叉搜索树,在进行插入和删除时通过特定操作保持二叉树自身的平衡,从而获得较高的查找 ...

  5. nyoj202 红黑树 (二叉树的左旋右旋)

    题目202 题目信息 运行结果 本题排行 讨论区 红黑树 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 什么是红黑树呢?顾名思义,跟枣树类似,红黑树是一种叶子是黑色果子 ...

  6. java数据结构红黑树上旋下旋_存储系统的基本数据结构之一: 跳表 (SkipList)

    在接下来的系列文章中,我们将介绍一系列应用于存储以及IO子系统的数据结构.这些数据结构相互关联又有着巨大的区别,希望我们能够不辱使命的将他们分门别类的介绍清楚.本文为第一节,介绍一个简单而又有用的数据 ...

  7. 【数据结构】利用4阶B树辅助理解——红黑树删除节点

    文章目录 学习目标: 学习内容: 一.删除节点的过程 二. 删除对象的转换 三.失黑的原因&失黑修正原则 3.1失黑的原因 3.2 失黑修正原则 3.2.1 可以在节点内部平衡的情况 3.2. ...

  8. 红黑树的节点颜色是什么决定_为什么选择颜色可能是您最重要的品牌决定

    红黑树的节点颜色是什么决定 This is a guest post by Max Ottignon, Co-founder, Ragged Edge. Ragged Edge is a brandi ...

  9. 红黑树:节点插入详解及其红黑树自我实现

    红黑树:节点插入详解及其红黑树自我实现 红黑树的四个性质: 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的 对于每个结点,从该结点到其所有后代叶结点的简单路 ...

最新文章

  1. 如何优化linux系统
  2. 餐饮供应链公司“鲜沐农场”获千万级Pre-A轮融资,未来要打造一站式采购平台...
  3. 测试nb信号的软件_NB-IoT和LORA,谁才是真正的低功耗?从数据看真相
  4. Linux学习之系统编程篇:练习验证线程共享全局变量
  5. 算法优化:最大m个子段和,问题规模从1个子段和扩展到m个,动态规划
  6. 【收藏】Android屏幕适配全攻略(最权威的Google官方适配指导)
  7. 现在做Android开发有前途吗?复习指南
  8. 前端学习(2837):image图片标签
  9. C#调用WebService实例和开发(转)
  10. Package vim is not available, but is referred to by another package.
  11. AcWing479.加分二叉树(区间DP)题解
  12. 第二课:更换国内下载源(阿里源为例)
  13. MATLAB 全景图切割及盒图显示
  14. MySQL - 21查询分析器EXPLAIN
  15. 【Java基础】基础概念与常识
  16. WEB应用项目开发-网店购物系统开发
  17. 计算机怎么弹奏送给未来的你,致未来的你经典句子 致未来的你好词好句
  18. kali、debian、Ubuntu中安装微信、qq、百度网盘
  19. 蓝桥杯-黑色星期五(算法训练)
  20. 在Mac下编译ijkplayer os文件

热门文章

  1. 联想台式机光驱拆除步骤
  2. [modem]AP和BP简介
  3. Ipage集合的遍历(取值/赋值)
  4. 10分钟,搞懂引力波
  5. pringboot冬奥会竞赛项目知识网站的设计与实现 毕业设计-附源码152337
  6. Generalizing from a Few Examples: A Survey on Few-Shot Learning 小样本学习最新综述| Introduction and Overview
  7. 我这个人有哪些优点,有哪些缺点
  8. 2021年中国氧气治疗仪市场趋势报告、技术动态创新及2027年市场预测
  9. SQLAlchemy:python数据库连接 神器
  10. Solana CEO做客吉姆 · 克莱默《Mad Money》谈融资后规划