JAVA 实现 - 红黑树
红黑树也是一种自平衡的二叉搜索树,较之AVL,插入和删除时旋转次数更少
红黑树特性:
- 所有节点都有两种颜色:红与黑
- 所有null 视为黑色
- 红色节点不能相邻
- 根节点时黑色
- 从根到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)
满足3,4,5 即位平衡
左旋
package com.datastructure.binarytree.redblacktree;
public class RedBlackTree {
enum Color{
RED,BALCK
}
private static class Node{
int key;
Object value;
Node left;
Node right;
Node parent; //父节点
Color color = Color.RED; //颜色
//是否是左孩子
boolean isLeftChild(){
return parent != null && parent.left == this;
}
//返回叔叔节点
Node uncle(){
if(parent == null || parent.parent == null){
return null;
}
if (isLeftChild()){
return parent.parent.right;
}else{
return parent.parent.left;
}
}
//返回兄弟节点
Node sibling(){
if (parent == null){
return null;
}
if(isLeftChild()){
return parent.right;
}else{
return parent.left;
}
}
}
//判断是否是红色节点
public boolean isRed(Node node){
return node != null && node.color == Color.RED;
}
//判断是否是黑色节点
public boolean isBlack(Node node){
return node == null || node.color == Color.BALCK;
}
Node root;
/*
右旋:
1.获取粉色、黄色、绿色、节点 (粉色:下移;黄色:上移;绿色:换爹)
2.三色节点的parent的处理
3.旋转后新根的父节点的处理
*/
private void rightRotate(Node pick){
Node parent = pick.parent; //记录旋转前时粉色节点的父节点
Node yellow = pick.left;
Node green = yellow.right;
if(green != null) {
green.parent = pick;
}
yellow.right = pick;
yellow.parent = parent;
pick.left = green;
pick.parent = yellow;
//建立更上层节点的父子关系
if (parent == null){
root = yellow;
} else if(parent.left == pick){
parent.left = yellow;
}else{
parent.right = yellow;
}
}
private void leftRotate(){
}
}
插入节点
插入节点
情况1: 插入节点为根节点,将根节点变黑
情况2: 插入节点的父亲若为黑色,树的红黑性质不变,无须调整
插入节点的父亲为红色,触发红红相邻
情况3: 叔叔为红色
3.1 父亲变为黑色,为了保证黑色平衡,连带的叔叔也变为黑色
3.2 祖父如果是黑色不变,会造成这颗子树黑色过多,因此祖父节点变为红色
3.2 祖父如果变为红色,可能会触发红红相邻,因此将祖父进行递归调整
情况4: 叔叔为黑色
4.1 父亲为左孩子,插入节点也是左孩子,此时LL不平衡
4.2 父亲为左孩子,插入节点是右孩子,此时即LR不平衡
4.3 父亲为右孩子,插入节点也是后孩子,此时即RR不平衡
4.4 父亲为右孩子,插入节点是左孩子,此时即RL不平衡
情况4.1 平衡过程:
8,7,9,12,11 RL
情况4.2 平衡过程:
8,5,10,3,4 LR
package com.datastructure.binarytree.redblacktree;
public class RedBlackTree {
...
public void put(int key, Object value) {
Node curr = root;
Node parent = null;
while (curr != null) {
parent = curr;
if (key < curr.key) {
curr = curr.left;
} else if (curr.key < key) {
curr = curr.right;
} else {
curr.value = value; //找到
return;
}
}
//没找到
Node inserted = new Node(key, value);
//找爹
if (parent == null) { //空树
root = inserted;
} else if (key < parent.key) {
parent.left = inserted;
inserted.parent = parent;
} else {
parent.right = inserted;
inserted.parent = parent;
}
fixRedRed(inserted); //处理红红
}
void fixRedRed(Node x) {
if (x == root) {
root.color = Color.BALCK;
return;
}
if (isBlack(x.parent)) {
return;
}
//触发红红相邻
Node parent = x.parent;
Node uncle = x.uncle();
Node grandparent = parent.parent;
if (isRed(uncle)) {
//变色
uncle.color = Color.BALCK;
parent.color = Color.BALCK;
grandparent.color = Color.RED;
fixRedRed(grandparent);
return;
}
//叔叔为黑色
if (parent.isLeftChild() && x.isLeftChild()) { //LL不平衡
parent.color = Color.BALCK;
grandparent.color = Color.RED;
rightRotate(grandparent);
} else if (parent.isLeftChild() && !x.isLeftChild()) { //LR
leftRotate(parent);
x.color = Color.BALCK;
grandparent.color = Color.RED;
rightRotate(grandparent);
} else if (!parent.isLeftChild() && !x.isLeftChild()) { //RR
parent.color = Color.BALCK;
grandparent.color = Color.RED;
leftRotate(grandparent);
} else { //RL
rightRotate(parent);
x.color = Color.BALCK;
grandparent.color = Color.RED;
rightRotate(grandparent);
}
}
}
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/17949151
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!