关于红黑树这一篇就够了

红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它满足以下五个特性:

  1. 每个节点要么是红色,要么是黑色
  2. 根节点是黑色的
  3. 所有叶子节点(NIL节点,空节点)是黑色的
  4. 如果一个节点是红色的,则它的两个子节点都是黑色的(从每个叶子到根的所有路径上不能有两个连续的红色节点)。
  5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点(称为黑高度)。

特点

  1. 自动平衡:红黑树通过旋转和重新着色操作来保持树的平衡,从而确保查询、插入和删除操作的时间复杂度都是对数级别的。

  2. 高效:由于红黑树的平衡性,使得查找、插入和删除等操作的时间复杂度都是O(log n),其中n是树中节点的数量。

  3. 黑高度平衡:红黑树保证了从根到叶子节点的最长路径不会超过最短路径的两倍,从而保证了树的平衡性。

基本操作(Java实现)

由于红黑树的实现相对复杂,这里只给出一些基本操作的基本思路和伪代码,并不提供完整的Java实现。

插入操作
  1. 将新节点插入为红色。
  2. 如果违反了性质4(即新节点的父节点是红色),则进行颜色调整。
  3. 如果违反了性质5(即黑高度不平衡),则进行旋转操作。
删除操作
  1. 如果要删除的节点有两个子节点,则找到其后继节点(或前驱节点),用后继节点(或前驱节点)的值替换要删除的节点,并删除后继节点(或前驱节点)。
  2. 将要删除的节点(或其替代节点)的颜色设为红色(如果原本是黑色)。
  3. 如果违反了性质5(即黑高度不平衡),则进行旋转和颜色调整操作。
旋转操作

旋转操作包括左旋和右旋,它们用于在插入或删除节点后重新平衡树。

  • 左旋:将当前节点的右子节点提升为当前节点的父节点,并将当前节点变为右子节点的左子节点。
  • 右旋:将当前节点的左子节点提升为当前节点的父节点,并将当前节点变为左子节点的右子节点。
颜色调整

颜色调整操作通常与旋转操作一起使用,用于在插入或删除节点后保持红黑树的性质。

注意事项

红黑树的实现需要仔细处理各种边界情况和特殊情况,以确保树的正确性和平衡性。因此,在实际编写红黑树的代码时,需要特别注意各种细节和异常情况的处理。

public class RedBlackTree<T extends Comparable<T>> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node<T> {
T key;
Node<T> left;
Node<T> right;
Node<T> parent;
boolean color;
Node(T key, boolean color, Node<T> parent) {
this.key = key;
this.color = color;
this.parent = parent;
this.left = null;
this.right = null;
}
}
private Node<T> root;
// 旋转操作
private void rotateLeft(Node<T> x) {
Node<T> y = x.right;
x.right = y.left;
if (y.left != null) {
y.left.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
root = y;
} else if (x == x.parent.left) {
x.parent.left = y;
} else {
x.parent.right = y;
}
y.left = x;
x.parent = y;
}
private void rotateRight(Node<T> y) {
Node<T> x = y.left;
y.left = x.right;
if (x.right != null) {
x.right.parent = y;
}
x.parent = y.parent;
if (y.parent == null) {
root = x;
} else if (y == y.parent.left) {
y.parent.left = x;
} else {
y.parent.right = x;
}
x.right = y;
y.parent = x;
}
// 插入修复
private void fixInsert(Node<T> k) {
while (k.parent != null && k.parent.color == RED) {
if (k.parent == k.parent.parent.right) {
Node<T> u = k.parent.parent.left;
if (u != null && u.color == RED) {
k.parent.color = BLACK;
u.color = BLACK;
k.parent.parent.color = RED;
k = k.parent.parent;
} else {
if (k == k.parent.left) {
k = k.parent;
rotateRight(k);
}
k.parent.color = BLACK;
k.parent.parent.color = RED;
rotateLeft(k.parent.parent);
}
} else {
// 镜像处理左子树的情况
Node<T> u = k.parent.parent.right;
if (u != null && u.color == RED) {
k.parent.color = BLACK;
u.color = BLACK;
k.parent.parent.color = RED;
k = k.parent.parent;
} else {
if (k == k.parent.right) {
k = k.parent;
rotateLeft(k);
}
k.parent.color = BLACK;
k.parent.parent.color = RED;
rotateRight(k.parent.parent);
}
}
}
root.color = BLACK;
}
// 插入新节点
public void insert(T key) {
Node<T> y = null;
Node<T> x = root;
while (x != null) {
y = x;
if (key.compareTo(x.key) < 0) {
x = x.left;
} else {
x = x.right;
}
}
Node<T> z = new Node<>(
Node<T>(key, RED, y);
if (y == null) {
root = z;
} else if (key.compareTo(y.key) < 0) {
y.left = z;
} else {
y.right = z;
}
// 修复插入后的红黑树性质
fixInsert(z);
}
// 中序遍历(用于打印树结构)
private void inorder(Node<T> root) {
if (root != null) {
inorder(root.left);
System.out.print(root.key + " ");
inorder(root.right);
}
}
// 主函数或测试代码
public static void main(String[] args) {
RedBlackTree<Integer> tree = new RedBlackTree<>();
// 插入元素进行测试
tree.insert(3);
tree.insert(1);
tree.insert(4);
tree.insert(2);
tree.insert(5);
tree.insert(0);
// 打印树结构
System.out.println("Inorder traversal of the constructed tree: ");
tree.inorder(tree.root);
}
}

这段代码提供了一个完整的红黑树实现,包括插入、修复插入后红黑树性质的方法以及中序遍历用于打印树结构。main 函数中创建了一个 RedBlackTree 对象,并插入了几个整数,然后打印了树的中序遍历结果。

请注意,由于红黑树的实现相对复杂,此代码仅作为一个基本的示例,可能还需要进一步的错误检查和优化,以确保在所有情况下都能正确工作。此外,对于删除操作和其他高级功能,如查找最小/最大元素、查找特定元素等,需要额外的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/599767.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Java EE] 多线程(九):ReentrantLock,Semaphore,CountDownLatch与线程安全的集合类(多线程完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

C++之类与对象

1、类声明 2、共有、私有、保护成员。&#xff08;就比如说你一个变量是private的&#xff0c;然后在main函数中&#xff0c;就调用不了&#xff0c;只能在这个类.cpp中调用&#xff09; 3、数据抽象和封装 4、内联函数 内存体积会增大&#xff0c;以空间换时间&#xff1a;编…

php使用服务器端和客户端加密狗环境部署及使用记录(服务器端windows环境下部署、linux环境宝塔面板部署、客户端部署加密狗)

php使用服务器端和客户端加密狗环境部署及使用记录 ViKey加密狗环境部署1.windows环境下部署开发文档验证代码提示Fatal error: Class COM not found in 2.linux环境下部署&#xff08;宝塔面板&#xff09;开发文档验证代码提示Fatal error: Uncaught Error: Call to undefine…

【软测学习笔记】Python入门Day02

&#x1f31f;博主主页&#xff1a;我是一只海绵派大星 &#x1f4da;专栏分类&#xff1a;软件测试笔记 &#x1f4da;参考教程&#xff1a;黑马教程❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ python安装 1、进入Python的官方下载页面&#xff1a; Download Python | Py…

Java+SpringBoot+JSP实现在线心理评测与咨询系统

前言介绍 随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门就可以通过网络进行系统管理&#xff0c;交易等&#xff0c;而且过程简单、快捷。同样的&#xff0c;在人们的工作生活中&#xff0c;也就…

用PowerPoint创建毛笔字书写动画

先看看下面这个毛笔字书写动画&#xff1a; 这个动画是用PowerPoint创建的。下面介绍创建过程。 1、在任何一款矢量图片编辑软件中创建一个图片&#xff0c;用文字工具输入文字内容。我用的是InkScape。排好版后将图片保存为.svg格式的矢量图片文件。 2、打开PowerPoint&…

RTT潘多拉开发板上实现电源管理

简介 随着物联网(IoT)的兴起&#xff0c;产品对功耗的需求越来越强烈。作为数据采集的传感器节点通常需要在电池供电时长期工作&#xff0c;而作为联网的SOC也需要有快速的响应功能和较低的功耗。 在产品开发的起始阶段&#xff0c;首先考虑是尽快完成产品的功能开发。在产品…

C++变量的作用域与存储类型

一 变量的作用域和存储类型 1 变量的作用域(Scope) 指在源程序中定义变量的位置及其能被读写访问的范围分为局部变量(Local Variable)和全局变量(Global Variable) 1&#xff09;局部变量(Local Variable) 在语句块内定义的变量 形参也是局部变量 特点&#xff1a; 生存期是…

web 基础之 HTTP 请求

web 基础 网上冲浪 就是在互联网(internet)上获取各种信息&#xff0c;进行工作&#xff0c;或者娱乐&#xff0c;他的英文表示surfing the Internet&#xff0c;因 “surfing”d的意思是冲浪&#xff0c;即成为网上冲浪&#xff0c;这是一种形象说法&#xff0c; 也是一个非…

交易复盘-20240507

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 蔚蓝生物 (5)|[9:25]|[36187万]|4.86 百合花…

SpringBootWeb入门

SpringBoot可以帮助我们快速的构建应用程序、简化开发、提高效率 创建SpringBoot工程&#xff0c;并勾选web开发相关依赖 定义HelloController类&#xff0c;添加方法&#xff0c;并添加注解 运行测试 创建SpringBoot工程(联网下载) 在File里面点击new Module 点击next 修…

Linux\_c输出

第一条Linux_c输出 初界面 : ls # 显示目录下的文件cd # 进入到某个目录 # 比如 我进入了Codels # 发现没有显示, 说明为文件下为空vim cpucdoe.c # 创建一个 .c的源码文件进入到了vim的编辑界面: i # 按i 就可以进行编辑 , 下面显示插入标识在编辑模式下, 可以通…

计算图:深度学习中的链式求导与反向传播引擎

在深度学习的世界中&#xff0c;计算图扮演着至关重要的角色。它不仅是数学计算的图形化表示&#xff0c;更是链式求导与反向传播算法的核心。本文将深入探讨计算图的基本概念、与链式求导的紧密关系及其在反向传播中的应用&#xff0c;旨在为读者提供一个全面而深入的理解。 计…

练习项目后端代码解析切面篇(Aspect)

前言 之前注解篇时我说&#xff0c;通常情况下一个自定义注解一般对应一个切面&#xff0c;虽然项目里的切面和注解个数相同&#xff0c;但是好像有一个名字看起来并不对应&#xff0c;无所谓&#xff0c;先看了再说。 ExceptionLogAspect切面 我在里面做了具体注释&#x…

使用Simulink Test进行单元测试

本文摘要&#xff1a;主要介绍如何利用Simulink Test工具箱&#xff0c;对模型进行单元测试。内容包括&#xff0c;如何创建Test Harness模型&#xff0c;如何自动生成excel格式的测试用例模板来创建测试用例&#xff0c;如何手动填写excel格式的测试用例模板来手动创建测试用例…

Golang Map类型

文章目录 Map介绍Map的定义方式Map的增删查改新增和修改Map元素查找Map元素删除Map元素遍历Map元素 Map元素排序Map切片 Map介绍 Map介绍 在Go中&#xff0c;map是哈希表的引用&#xff0c;是一种key-value数据结构。map类型写作map[K]V&#xff0c;其中K和V分别对应key和value…

系统维护启动盘 优启吧

优启吧-《优启时代系统维护盘》2025典藏版&#xff08;UD/ISO&#xff09;

亿发解密:数据中台管理系统,引领企业数字化转型的智能数据体系

在当今数字化时代&#xff0c;数据已成为企业发展的关键驱动力。为了更好地利用数据&#xff0c;提升业务水平&#xff0c;企业需要建立一套完备的数据管理体系&#xff0c;而数据中台便应运而生。 什么是数据中台 数据中台是集方法论、组织和工具于一体的智能大数据体系。它…

一起深度学习(AlexNet网络)

AlexNet神经网络 代码实现&#xff1a; 代码实现&#xff1a; import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(# 采用了11*11的卷积核来捕捉对象&#xff0c;因为原始输入数据比较大#步幅为4 &#xff0c;可减少输出的高度核宽度。#输出通…

微搭低代码入门06分页查询

目录 1 创建自定义代码2 编写分页代码3 创建页面4 创建变量5 配置数据列表总结 我们在数据模型章节介绍了微搭后端服务编写的三种方式&#xff0c;包括Http请求、自定义代码、云函数。本篇我们详细讲解一下利用自定义代码开发分页查询的功能。 1 创建自定义代码 打开控制台&am…
最新文章