JAVA红黑树TreeMap/TreeSet详解

Java中的红黑树是一种自平衡的二叉查找树,它通过特定的旋转和重新着色操作来确保树的高度大致保持在对数级别,从而在平均和最坏情况下都能保证查找、插入、删除等操作的时间复杂度为O(log n)。红黑树通过遵循一系列的性质来维持其平衡:

红黑树的性质

  1. 节点是红色或黑色
    • 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色
    • 这有助于确保从根到叶子的最长路径不会比最短路径长两倍以上。
  3. 所有叶子(NIL节点,空节点)都是黑色
    • 这里的叶子指的是树尾端的空(NIL)节点。
  4. 如果一个节点是红色的,则它的两个子节点都是黑色的(也就是从每个叶子到根的所有路径上不能有两个连续的红色节点):
    • 这有助于确保树大致上是平衡的。
  5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
    • 这被称为黑高(black-height)性质,保证了树的高度大致是对数级别的。

使用条件

  1. 需要保持元素有序:当你需要存储的元素集合需要保持有序时,红黑树是一个很好的选择。它可以确保在插入、删除和查找操作中,元素始终按照某种顺序(通常是键的自然顺序或自定义的比较器顺序)排列。

  2. 需要高效的查找、插入和删除操作:红黑树通过保持树的平衡(即确保树的高度大致是对数级别的),来保证这些操作的高效性。在最坏情况下,这些操作的时间复杂度都是O(log n),其中n是树中元素的数量。

  3. 可以接受一定的额外开销:虽然红黑树提供了优秀的性能保证,但它也引入了一些额外的开销,比如插入和删除时可能需要的旋转和重新着色操作。这些操作会增加一些额外的计算成本。因此,在性能要求极高且对额外开销非常敏感的场景下,可能需要考虑其他数据结构。

使用场景

  1. 数据库和索引:在数据库和文件系统中,红黑树常被用作索引结构,以加速数据的查找、插入和删除操作。例如,B+树(一种基于红黑树思想的变体)在数据库索引中非常常见。

  2. 关联数组和映射:像Java中的TreeMapTreeSet这样的集合类,内部就是使用红黑树来实现的。它们提供了按键排序的映射和集合,适用于需要保持元素有序的场景。

  3. 实现优先队列:红黑树也可以用来实现优先队列(一种特殊的队列,其中每个元素都有一个优先级,元素的出队顺序按照优先级进行)。通过适当地调整节点的颜色,可以在红黑树上实现最小堆或最大堆的功能。

  4. 图论算法中的数据结构:在某些图论算法中,如Dijkstra算法(用于计算图中单源最短路径)的实现中,可以使用红黑树来维护一个按距离排序的节点集合,以便高效地选择下一个要处理的节点。

  5. 其他需要自平衡二叉查找树的场景:除了上述场景外,任何需要自平衡二叉查找树的场景都可以考虑使用红黑树。例如,在实现某些类型的平衡树数据结构时,红黑树可以作为一个基础选项。

 

红黑树的操作

插入
  • 插入新节点:首先像普通二叉查找树一样插入新节点,并默认将其着色为红色。
  • 调整:如果新节点的插入违反了红黑树的性质,则通过一系列的旋转(左旋、右旋)和重新着色操作来恢复性质。
删除
  • 删除节点:首先像普通二叉查找树一样删除节点。
  • 修复:删除节点后,可能需要一系列复杂的旋转和重新着色操作来恢复红黑树的性质。

Java中的红黑树实现

在Java中,TreeMap 和 TreeSet 都是通过红黑树实现的。这意味着这些集合在保持元素有序的同时,也提供了高效的查找、插入和删除操作。

示例

例1:TreeMap

import java.util.TreeMap;  public class RedBlackTreeExample {  public static void main(String[] args) {  TreeMap<Integer, String> map = new TreeMap<>();  map.put(1, "One");  map.put(3, "Three");  map.put(2, "Two");  // TreeMap会按照键的自然顺序进行排序  System.out.println(map); // 输出: {1=One, 2=Two, 3=Three}  // TreeMap的键集合和值集合都是按照排序后的顺序排列的  System.out.println(map.keySet()); // 输出: [1, 2, 3]  System.out.println(map.values()); // 输出: [One, Two, Three]  }  
}

例2:TreeSet

import java.util.TreeSet;  public class TreeSetExample {  public static void main(String[] args) {  // 创建一个 TreeSet 实例  TreeSet<Integer> numbers = new TreeSet<>();  // 向 TreeSet 中添加元素  numbers.add(3);  numbers.add(1);  numbers.add(4);  numbers.add(1); // 尝试添加重复元素,不会成功  numbers.add(2);  // 遍历并打印 TreeSet 中的元素  // 由于 TreeSet 是基于红黑树实现的,所以它会按照元素的自然顺序(或指定的 Comparator 顺序)进行排序  for (Integer number : numbers) {  System.out.println(number);  }  // 输出结果将会是排序后的元素列表:1, 2, 3, 4  // 如果你想要按照自定义的顺序对 TreeSet 中的元素进行排序,  // 可以在创建 TreeSet 时提供一个 Comparator 实例  TreeSet<String> names = new TreeSet<>((a, b) -> b.compareTo(a)); // 使用自定义比较器,按字符串的逆序排序  names.add("Alice");  names.add("Bob");  names.add("Charlie");  // 遍历并打印 names TreeSet 中的元素  for (String name : names) {  System.out.println(name);  }  // 输出结果将会是自定义排序后的元素列表:Charlie, Bob, Alice  }  
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

培训班和科班出生有什么区别

IT业的萌新来啦 每到毕业季 总有大量萌新走进职场 IT圈子的程序员 有的是科班出生 比如 计算机科学与技术、软件工程、大数据技术 有的是相关专业出生的 比如 信息安全、网络工程、物联网工程等等 除此之外 还有各种其他专业转行过来的 文理不限、专业不限 科班出生…

【在Linux世界中追寻伟大的One Piece】IO基础

目录 1 -> 回顾 1.1 -> 回顾C文件接口 1.2 -> 总结 2 -> 系统文件I/O 3 -> 接口介绍 3.1 -> open 3.2 -> open函数返回值 3.3 -> 文件描述符fd 4 -> 0 & 1 & 2 5 -> 文件描述符的分配规则 6 -> 重定向 7 -> 使用dup2系…

运维开发——局域网SSH访问服务器与应用

摘要 本博文主要介绍局域网SSH访问登陆虚拟机和及其应用相关配置操作。 1. 局域网SSH访问登陆虚拟机 目标&#xff1a;在局域网内A电脑使用SSH登陆B电脑上虚拟机的服务器。 前提条件:B电脑为宿主机&#xff0c;可以正常使用ssh访问虚拟机服务器&#xff0c;虚拟机网络连接方…

WPS宏实现表格合并功能

把文件夹中N个表格Sheet1页的数据合并成一个新的表格 function 合并表格() { //合并文件为C盘下面名为test的文件夹 var folderPath "C:\\test"; var fileName Dir(folderPath "\\*.*"); if(fileName ""){ ale…

不同关键字的原子性、可见性、有序性之间的比较

一、多线程中有三个非常重要的特性 1. 原子性 在一次或者多次操作时&#xff0c;要么所有操作都被执行&#xff0c;要么所有操作都不执行 2. 有序性 程序执行的顺序按照代码的先后顺序执行&#xff0c;没有进行优化和顺序调整。 为了提高程序的运行效率&#xff0c;Java可能在…

深度学习基础—超参数调试

1.超参数调试顺序 在训练深度网络最难的事情之一是超参数的选择&#xff0c;如何选择合适的超参数取值&#xff1f;下面我将谈谈&#xff0c;如下是我所理解的超参数调试顺序&#xff1a; 重要性排序 超参数 Top1梯队 学习率a Top2梯队 min-batch大小&#xff0c;隐层神经…

书籍字符串的统计字符串(5)0823

题目 给定一个字符串str&#xff0c;返回str的统计字符串&#xff0c;例如“aaabbadddffc”的统计字符串为“a_3_b_2_a_1_d_3_f_2_c_1"。 补充题目 给定一个字符串的统计字符串cstr&#xff0c;再给定一个整数index&#xff0c;返回cstr所代表的原始字符串上的第index个…

QT-五子棋游戏

QT-五子棋游戏 一、演示效果二、核心代码三、下载链接 一、演示效果 二、核心代码 #include "GameModel.h" #include <time.h> #include <stdlib.h>GameModel::GameModel(){}void GameModel::startGame(GameType type){gameType type;//初始化棋盤game…

uniapp/vue如何实现一个子表单及子表单作用

子表单是一个辅助表单或一个表&#xff0c;它允许在主表单中添加多个行式项目&#xff0c;以处理与主记录相关联的多个辅助项目或数据。子表单在多种应用场景中发挥着重要作用&#xff0c;特别是在需要处理一对多关系的数据时。 以下是对子表单的详细解析&#xff1a; 定义与特…

nvm安装node找不到版本问题(只有iojs)

&#x1f506; 背景 很久没有使用nvm新安装node版本了&#xff0c;今天在切换时执行 nvm install 要执行很久&#xff0c;然后返回暂无当前版本的错误信息&#xff0c;那就执行 nvm ls-remote 看一下远程的版本&#xff0c;发现返回的只有iojs的版本&#xff0c;没有node版本&…

90%的设计师都不知道的免抠图素材插件,水花免抠png素材轻松搞定!附保姆教程

你是否曾在设计中为绘制那些晶莹剔透的水花而苦恼&#xff1f;用PS太麻烦&#xff0c;细节根本抠不清楚&#xff1b;去素材网找&#xff0c;不是付费太高就是图案不满意&#xff01;可以试试千鹿设计助手的“AI免抠生成”插件&#xff0c;接下来我来分享一下我的一些使用过程和…

LeetCode 3133.数组最后一个元素的最小值:位运算+双指针

【LetMeFly】3133.数组最后一个元素的最小值&#xff1a;位运算双指针 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-array-end/ 给你两个整数 n 和 x 。你需要构造一个长度为 n 的 正整数 数组 nums &#xff0c;对于所有 0 < i < n - 1 &#xff0…

ardupilot开发 --- C嘎嘎 篇

长生不老&#xff1f;三界六道不就毁在这4个字上&#xff1f; 溜撒点一起上吧 cout和cin的使用&#xff0c;标准输入输出<< 和 >> 的使用数据类型&#xff08;函数&#xff09;模板的使用&#xff1a;命名空间的使用&#xff0c;std命名空间语句块new 的使用引用 &…

fiddler在软件测试中的使用(详细版)

1.抓包&#xff0c;辅助定位bug&#xff08;web中类似谷歌浏览器F12开发调试工具&#xff09; 合格的软件测试工程师&#xff0c;不仅仅需要能够发现bug&#xff0c;还需要能透过bug表象&#xff0c;分析出问题根本原因&#xff0c;从而提升bug的解决效率&#xff0c;通过fidd…

微信小程序记录(持续更新)

1.登录相关 登录简单来说就是用uni.login获取登陆凭证code。然后调用后台登录接口传递给后台&#xff0c;后台解码再返回token等一系列信息给前端 参考地址&#xff1a; 微信小程序获取用户手机号码教程&#xff08;前端后端&#xff09;_微信小程序获取手机号-CSDN博客 代码…

【pytorch】固定(freeze)住部分网络

https://blog.csdn.net/jningwei/article/details/120300014 如果使用过了FSDP架构&#xff0c;需要使用pytorch2.0以上的版本。 use_orig_paramstrue ignored_parameters[param for param in model.parameters() if not param.requires_grad] # 如果是2.1.0以上版本&#xf…

Qt音视频处理类有这些

Qt 提供了一系列音视频处理的类&#xff0c;这些类可以帮助开发者实现音视频的播放、录制、编解码等功能。以下是 Qt 中一些主要的音视频类&#xff1a; QMediaPlayer: 用于播放音频和视频的类&#xff0c;支持多种媒体格式&#xff0c;可以控制播放、暂停、停止等基本操作 。…

手机使用技巧:如何恢复Android手机不见的短信

在您的 Android 手机上丢失短信可能是一种令人沮丧的经历&#xff0c;尤其是在文本包含重要信息的情况下。幸运的是&#xff0c;有一些方法可以在Android上恢复已删除的短信。在这篇博文中&#xff0c;我们将讨论几种在Android手机上恢复已删除短信的方法。 为什么需要恢复Andr…

vue2版本空目录下创建新项目的方法2024

vue2版本空目录下创建新项目的方法2024 node -v npm -v vue -V 安装vue-cli 2.9版本的命令 npm install vue-cli -g 卸载vue2.x方法&#xff1a; npm uninstall vue-cli -g 设置 NPM 镜像 npm config set registry https://registry.npmmirror.com vue -V 报错时需设置环…

JVM的内存模型和垃圾回收

JVM内存区域 内存模型图&#xff1a; 堆 线程共享。所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。 它的目的是存放对象实例。同时它也是GC所管理的主要区域&#xff0c;因此常被称为GC堆&#xff0c;又由于现在收集器常使用分代算法&#xff0c;Java堆中还…