当前位置: 首页 > news >正文

浅淡红黑树以及其在Java中的实际应用

浅淡红黑树以及其在Java中的实际应用

一、红黑树简介

红黑树是一种自平衡的二叉查找树(Binary Search Tree,简称 BST)。它的特点是通过对节点的颜色进行标记,确保树的高度尽量保持平衡,从而使得在最坏情况下,查找、插入和删除操作的时间复杂度都能保持在 O(log n)。

红黑树的设计思想是通过严格的规则来控制树的高度,避免树的结构变得过于倾斜,从而提升操作效率。

二、红黑树的性质

红黑树有以下五个性质:

  • 每个节点是红色或黑色:树中的每个节点要么是红色,要么是黑色。
  • 根节点是黑色:树的根节点总是黑色。
  • 每个叶子节点(NIL节点)是黑色:即树的空子节点是黑色。
  • 红色节点不能相邻:红色节点的子节点必须是黑色的(即红色节点不能连续出现在树中)。
  • 从任意节点到其所有后代叶子节点的路径上,黑色节点的个数必须相同:这个条件确保了树的平衡性。

这些性质通过控制树的高度差异来保证红黑树始终保持平衡,使得每次操作的时间复杂度为 O(log n)。

三、红黑树的操作

在红黑树中,常见的操作包括 插入 和 删除,这些操作会保持树的红黑性质。为了确保这些性质,插入和删除操作后可能需要进行 旋转 和 重新着色。

插入操作的过程:

1.常规的二叉查找插入:按照普通的二叉查找树规则进行插入。
2.调整红黑性质:

  • 插入的节点通常是红色节点。
  • 如果插入的节点违反了红黑树的规则(例如,父节点和插入节点都是红色),则通过旋转和重新着色来恢复平衡。
旋转操作:
  • 左旋:将一个节点的右子树提升为该节点,原来的节点变为左子树。
  • 右旋:与左旋相反,将一个节点的左子树提升为该节点,原来的节点变为右子树。

旋转的目的是通过调整树的结构,改变某些节点的父子关系,保持树的平衡。

举个例子:红黑树的插入过程

假设我们要向一个空的红黑树中插入数字 30、20、10、25、5 的顺序。

  • 插入 30:

    • 30 成为根节点,根节点必定是黑色。
      在这里插入图片描述
  • 插入 20:

    • 20 比 30 小,因此插入到 30 的左边。20 是红色,因为它是刚插入的节点。
      在这里插入图片描述
  • 插入 10:

    • 10 比 30 小,比 20 小,所以插入到 20 的左边。插入节点 10 是红色。
      在这里插入图片描述

    • 由于 20 和 10 都是红色,这违反了红黑树的性质:红色节点不能有红色子节点。为了修复这个问题,我们需要进行旋转和重新着色。
      在这里插入图片描述

  • 插入 25:

    • 25 比 30 小,但比 20 大,所以插入到 20 的右边。插入节点 25 是红色。
      在这里插入图片描述
  • 插入 5:

    • 5 比 30 小,比 20 小,比 10 小,插入到 10 的左边。插入节点 5 是红色。
      在这里插入图片描述

tips: 上述演示可以通过网站进行在线模拟:演示链接

四、为什么要使用红黑树?

红黑树的主要优势在于它提供了良好的平衡性,确保了在最坏情况下操作的时间复杂度为 O(log n)。这对于大量数据的插入、删除和查找操作来说非常重要,尤其是在需要频繁操作数据时。

红黑树常用于以下场景:

  • STL(标准模板库)中的 map 和 set:这些数据结构通常是基于红黑树实现的。
  • 数据库索引:为了快速查找、插入和删除数据,许多数据库引擎采用了红黑树或类似的平衡树。
五、红黑树在Java中的实际应用
1. TreeMap 和 TreeSet

Java 中的 TreeMap 和 TreeSet 都是基于红黑树实现的,它们提供了按 自然顺序 或指定的 比较器 排序的数据存储。它们都可以支持 有序集合,并提供 O(log n) 时间复杂度的常见操作,如 查找、插入和删除。

  • TreeMap:实现了 Map 接口,它是一种基于键值对的有序映射。它保证了键是有序的,并且根据键的大小顺序进行排序。TreeMap 的常见操作,如 get()、put()、remove() 等,都是在 O(log n) 时间内完成的。
  • TreeMap和HashMap的区别
import java.util.*;

public class TreeMapExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(3, "Three");
        map.put(1, "One");
        map.put(2, "Two");

        System.out.println(map);  // 输出:{1=One, 2=Two, 3=Three}
    }
}
  • TreeSet:实现了 Set 接口,它存储的是不重复的元素,并且保证元素按照一定顺序(默认是自然顺序)进行排序。TreeSet 适用于需要去重并且保持顺序的场景。
import java.util.*;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(3);
        set.add(1);
        set.add(2);

        System.out.println(set);  // 输出:[1, 2, 3]
    }
}
2. NavigableMap 和 NavigableSet

TreeMap 和 TreeSet 实现了 NavigableMap 和 NavigableSet 接口,这两个接口提供了一些导航功能,例如可以获取比给定元素大的最小元素、比给定元素小的最大元素等。

TreeMap 实现了 NavigableMap,可以通过它提供的 ceilingKey()、floorKey() 等方法,快速找到相应的键。

import java.util.*;

public class NavigableMapExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(1, "One");
        map.put(2, "Two");
        map.put(3, "Three");

        // 返回大于或等于2的最小键
        System.out.println(map.ceilingKey(2));  // 输出:2

        // 返回小于或等于2的最大键
        System.out.println(map.floorKey(2));   // 输出:2
    }
}

TreeSet 实现了 NavigableSet,支持类似的导航方法,如 ceiling(), floor(), higher(), lower() 等。

import java.util.*;

public class NavigableSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(1);
        set.add(2);
        set.add(3);

        // 返回大于或等于2的最小元素
        System.out.println(set.ceiling(2));  // 输出:2

        // 返回小于或等于2的最大元素
        System.out.println(set.floor(2));   // 输出:2
    }
}
3. ConcurrentSkipListMap 和 ConcurrentSkipListSet

Java 还提供了 ConcurrentSkipListMap 和 ConcurrentSkipListSet,这两种数据结构与红黑树类似,但它们使用的是 跳表(Skip List)。跳表的实现和红黑树在设计理念上有所不同,但同样支持高效的查找、插入和删除操作,并且它们是线程安全的,适用于并发场景。

4. 实现优先队列

红黑树可以用来实现 优先队列(Priority Queue),在这个实现中,元素根据优先级进行排序。红黑树保证了每次出队操作都能以 O(log n) 的时间复杂度找到最小(或最大)元素。

然而,Java 标准库中使用的是基于堆(Heap)的 PriorityQueue,但理论上,红黑树可以作为一个优先队列的实现方式,支持快速的插入和删除。

5. 内存管理和调度

在某些高性能应用中,红黑树也可以用来实现 任务调度 和 内存管理。例如,在 操作系统 或 内存分配器 中,红黑树可以用来维护内存块的空闲列表,快速地分配和释放内存块。

六、总结

红黑树是一种自平衡的二叉查找树,它通过对节点进行颜色标记并遵守特定的规则,保证树的平衡性,确保查找、插入、删除操作的时间复杂度为 O(log n)。通过旋转和重新着色等操作,红黑树能够有效地避免树结构变得过于倾斜,提升数据操作的效率。

相关文章:

  • 【ACM MM会议-2024工业异常检测】FiLo++:融合细粒度描述和形变定位的零样本/少样本异常检测
  • IO多路复用沉浸式体验
  • OpenAI Gym 提供了丰富的强化学习测试环境
  • 并发阻塞队列原理分析
  • 用户自定义函数(UDF)开发与应用(二)
  • 快速幂运算
  • 阅读论文 smart pretrain,搭配MAE一起食用
  • Elasticsearch 性能优化:从原理到实践的全面指南
  • Elasticsearch入门指南(三) 之 高级篇
  • 2025蓝桥杯JavaB组真题解析
  • JavaScript性能优化(下)
  • Spring Boot集成Nacos
  • 【Web功能测试】Web商城搜索模块测试用例设计深度解析
  • 2025第十六届蓝桥杯PythonB组部分题解
  • [特殊字符] 第十七讲 | 随机森林:变量重要性识别与建模实战
  • 4月份到9月份看6本书第一天
  • 基于Flask-Login简单登录和权限控制实践
  • 句句翻译。
  • 平凡日子里的挣扎
  • 第7课:智能体安全与可靠性保障
  • 南方降水频繁暴雨连连,北方高温再起或现40°C酷热天气
  • 美国务院批准向土耳其出售导弹及相关部件,价值3.04亿美元
  • 广西北部湾国际港务集团副总经理潘料庭接受审查调查
  • 远如《月球背面》,近似你我内心
  • 阿尔巴尼亚执政党连续第四次赢得议会选举,反对党此前雇用特朗普竞选经理
  • 城市轨道交通安全、内河港区布局规划、扎实做好防汛工作……今天的上海市政府常务会议研究了这些重要事项