【数据结构和算法】--RangeSet时间范围管理示例

目录

  • 一、问题
  • 二、RangeSet实现原理
    • 2.1、RangeSet常用方法
    • 2.2、核心原理
    • 2.3、核心特性
    • 2.4、基本使用
  • 三、具体应用

一、问题

最近项目要求对一批时间范围进行管理,要求不能交叉。RangeSet是专门用于高效处理范围集合。

二、RangeSet实现原理

RangeSet表示一组不重叠的、非空的范围集合。RangeSet中的每个范围都是一个Range对象,Range对象表示一个具有起始和结束边界的范围。实现RangeSet接口,主要有两个实现类:ImmutableRangeSet和TreeRangeSet。ImmutableRangeSet是一个不可修改的RangeSet,而TreeRangeSet则是利用树的形式来实现,提供了高效的查询和插入操作。

2.1、RangeSet常用方法

complement():返回RangeSet的补集视图。complement也是RangeSet类型,包含了不相连的、非空的区间。
subRangeSet(Range<C>):返回RangeSet与给定Range的交集视图。这扩展了传统排序集合中的headSet、subSet和tailSet操作。
asRanges():用Set<Range<C>>表现RangeSet,这样可以遍历其中的RangeasSet(DiscreteDomain<C>)(仅ImmutableRangeSet支持):用ImmutableSortedSet<C>表现RangeSet,以区间中所有元素的形式而不是区间本身的形式查看。(这个操作不支持DiscreteDomainRangeSet都没有上边界,或都没有下边界的情况)
contains(C)RangeSet最基本的操作,判断RangeSet中是否有任何区间包含给定元素。
rangeContaining(C):返回包含给定元素的区间;若没有这样的区间,则返回nullencloses(Range<C>):简单明了,判断RangeSet中是否有任何区间包括给定区间。
span():返回包括RangeSet中所有区间的最小区间。

2.2、核心原理

RangeSet的实现原理主要基于一种称为“范围树”的数据结构。范围树是一种平衡树,其中每个节点都表示一个范围。树中的节点按照范围的起始位置进行排序,以便快速查找和定位特定的范围。
当向RangeSet中添加一个新的范围时,它会遍历范围树,找到与新范围相交或相邻的现有范围,并进行合并。合并后的范围会被插入到树中的适当位置,以保持树的平衡性。
对于查询操作,RangeSet可以利用范围树的结构进行快速查找。【例如,当查询一个元素是否包含在RangeSet中时,可以从树的根节点开始,沿着适当的分支向下遍历,直到找到一个包含该元素的范围或确定该元素不在RangeSet中。】

2.3、核心特性

自动合并范围
当向RangeSet中添加一个新的范围时,它会自动与现有的范围进行合并。如果新的范围与某个现有范围相交或相邻,它们会被合并成一个更大的范围。这种自动合并的特性使得RangeSet能够保持范围的不重叠性,从而简化了范围集合的管理。
高效的查询操作
RangeSet提供了丰富的查询操作,可以快速地判断一个元素是否在某个范围内、获取包含某个元素的范围等。这些查询操作都是基于对范围树的高效遍历实现的,能够在对数时间内给出结果。
灵活的范围操作
除了基本的查询操作外,RangeSet还支持各种范围操作,如并集、交集、差集等。这些操作可以方便地对范围集合进行组合和变换,满足各种复杂的需求。

2.4、基本使用

  public void way1(){RangeSet<Integer> rangeSet = TreeRangeSet.create();// 向RangeSet中添加几个不连续的范围rangeSet.add(Range.closed(1, 3));     // [1, 3]rangeSet.add(Range.open(5, 8));       // (5, 8)rangeSet.add(Range.closedOpen(10, 12));// [10, 12)rangeSet.add(Range.greaterThan(15));   // (15, +∞)// 打印当前RangeSet的内容System.out.println(rangeSet); // [1..3](5..8)[10..12)(15..+∞)// 查询某个范围是否包含在RangeSet中// System.out.println(rangeSet.contains(Range.closed(2, 3)));   // true// System.out.println(rangeSet.contains(Range.open(6, 7)));     // true// System.out.println(rangeSet.contains(Range.closed(11, 11))); // true// System.out.println(rangeSet.contains(Range.closed(4, 5)));   // false// 删除一个范围rangeSet.remove(Range.open(5, 8));System.out.println(rangeSet); // [1..3][10..12)(15..+∞)// 获取与指定范围重叠的范围RangeSet<Integer> overlappingRanges = rangeSet.subRangeSet(Range.atLeast(9));System.out.println(overlappingRanges); // [10..12)(15..+∞)// 获取指定范围的补集(这里仅展示与[0, 20]范围内的补集)RangeSet<Integer> complement = rangeSet.complement().subRangeSet(Range.closed(0, 20));System.out.println(complement); // (0..1)(3..5)(8..10)[12..15][15..20]// 注意:由于complement()返回的是整个数域中不属于rangeSet的部分,// 我们再次使用subRangeSet来限制补集的范围,以便更好地展示结果。// 查询单个元素是否在RangeSet中System.out.println(rangeSet.contains(2));    // trueSystem.out.println(rangeSet.contains(9));    // false// 获取包含指定元素的范围Range<Integer> rangeContaining11 = rangeSet.rangeContaining(11);System.out.println(rangeContaining11); // [10..12)Range<Integer> rangeContaining4 = rangeSet.rangeContaining(4);System.out.println(rangeContaining4); // null,因为4不在rangeSet中// 获取RangeSet的最小和最大元素(注意这不是一个Range,而是两个元素)Integer minValue = rangeSet.asRanges().stream().map(Range::lowerEndpoint).min(Integer::compareTo).orElse(null);Integer maxValue = rangeSet.asRanges().stream().map(Range::upperEndpoint).max(Integer::compareTo).orElse(null);System.out.println("Min value: " + minValue); // Min value: 1System.out.println("Max value: " + maxValue); // Max value: 2147483647 (Integer.MAX_VALUE,因为rangeSet包含(15..+∞))}

三、具体应用

yyyy-MM-dd类型的时间,要求构建范围,新加入的时间范围不可重叠。

 /**新加入的时间,如果有重叠,返回false* @param start  2024-04-03* @param end*/public Boolean addTimeToRange(String start,String end){Date startDate = TimeUtil.stringToDate(start,TimeUtil.D_FORMAT);Date endDate = TimeUtil.stringToDate(end,TimeUtil.D_FORMAT);long lStart = TimeUtil.dateToLong(startDate);long lEnd = TimeUtil.dateToLong(endDate);if(timeRangeValue.contains(lStart) || timeRangeValue.contains(lEnd)){return false;}timeRangeValue.add(Range.closed(lStart,lEnd));return true;}public Map<String,String> getTimeFromRange(){Map<String,String> reMap = new HashMap<>();Set<Range<Long>> ranges= timeRangeValue.asRanges();Iterator<Range<Long>> iterator = ranges.iterator();while (iterator.hasNext()){Range<Long> tempRange = iterator.next();Date dStart = TimeUtil.longToDate(tempRange.lowerEndpoint(),TimeUtil.D_FORMAT);Date dEnd = TimeUtil.longToDate(tempRange.upperEndpoint(),TimeUtil.D_FORMAT);reMap.put(TimeUtil.dateToString(dStart,TimeUtil.D_FORMAT),TimeUtil.dateToString(dEnd,TimeUtil.D_FORMAT));}return reMap;}public static void main(String[] args) {RangeCreateService rangeCreateService = new RangeCreateService();rangeCreateService.addTimeToRange("2024-01-02","2024-01-24");rangeCreateService.addTimeToRange("2024-02-05","2024-02-24");rangeCreateService.addTimeToRange("2024-01-24","2024-02-02");Map<String,String> reMap = rangeCreateService.getTimeFromRange();System.out.println("timeRangeValue:"+ JSON.toJSONString(reMap));}

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

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

相关文章

C语言中字符串输入的3种方式

Ⅰ gets() 函数 gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间 # include <stdio.h> int main(void) {char a[256] {0};gets(a);printf("%s",a);return 0; }Ⅱ getchar() # include <stdio.h> int mai…

工业光源环形系列一AOI光源特点

产品特点 ◆具有环形光源所有的特点&#xff1b; ◆采用不同角度多色光&#xff0c;使被照物体的成像更具立体特征&#xff1b; ◆每种颜色可独立控制。

论文辅助笔记:Tempo之modules/prompt.py

1 get_prompt_param_cls 2 get_prompt_value 3 Prompt 类 3.1 _init_weights 3.2 forward

Spring Security Oauth2 JWT 添加额外信息

目录 一、问题描述 二、实现步骤 1、自定义TokenEnhancer 2、配置授权服务器 3、自定义UserDetails的User类 三、参考文档 一、问题描述 Oauth2里默认生成的JWT信息并没有用户信息&#xff0c;在认证授权后一般会返回这一部分信息&#xff0c;我对此进行了改造。 Oauth…

CC工具箱使用指南:【按属性分割成SHP】

一、简介 Arcgis中有一个【按属性分割】的工具&#xff0c;可以将要素类按字段值分割成多个gdb要素类&#xff0c;也可以分割成多个SHP要素。 这个工具是在【按属性分割】工具的基础上做了一个强化&#xff0c;可以将分割出来的SHP要素分别放在独立的文件夹内。 实际工作中&…

Java | Leetcode Java题解之第70题爬楼梯

题目&#xff1a; 题解&#xff1a; public class Solution {public int climbStairs(int n) {double sqrt5 Math.sqrt(5);double fibn Math.pow((1 sqrt5) / 2, n 1) - Math.pow((1 - sqrt5) / 2, n 1);return (int) Math.round(fibn / sqrt5);} }

爬虫工具:避免复制文字收费,VIP。。

step ctrl shift i 打开开发者工具 点击...打开设置勾选禁用JavaScript Principle 事件处理&#xff1a;JavaScript 用于处理用户交互&#xff0c;例如点击、滚动、输入等禁用 JavaScript 后&#xff0c;页面上的所有 JavaScript 代码都将不会执行

学习网络安全 你必须要学会的20款工具

工欲善其事必先利其器&#xff0c;在新入门网络安全的小伙伴而言。这些工具你必须要有所了解。本文我们简单说说这些网络安全工具吧&#xff01; Web安全类 Web类工具主要是通过各种扫描工具&#xff0c;发现web站点存在的各种漏洞如sql注入、xss等。从而获取系统权限&#xf…

IoTDB 入门教程 基础篇⑦——数据库管理工具 | DBeaver 连接 IoTDB

文章目录 一、前文二、下载iotdb-jdbc三、安装DBeaver3.1 DBeaver 下载3.2 DBeaver 安装 四、安装驱动五、连接数据库六、参考 一、前文 IoTDB入门教程——导读 二、下载iotdb-jdbc 下载地址org/apache/iotdb/iotdb-jdbc&#xff1a;https://maven.proxy.ustclug.org/maven2/o…

stamps做sbas-insar,时序沉降图怎么画?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【人工智能Ⅱ】实验5:自然语言处理实践(情感分类)

实验5&#xff1a;自然语言处理实践&#xff08;情感分类&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;掌握RNN、LSTM、GRU的原理。 2&#xff1a;学习用RNN、LSTM、GRU网络建立训练模型&#xff0c;并对模型进行评估。 3&#xff1a;学习用RNN、LSTM、GRU网络做…

AST原理(反混淆)

一、AST原理 jscode var a "\u0068\u0065\u006c\u006c\u006f\u002c\u0041\u0053\u0054";在上述代码中&#xff0c;a 是一个变量&#xff0c;它被赋值为一个由 Unicode 转义序列组成的字符串。Unicode 转义序列在 JavaScript 中以 \u 开头&#xff0c;后跟四个十六进…

Python学习笔记------json

json简介 JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据 JSON本质上是一个带有特定格式的字符串 主要功能&#xff1a;json就是一种在各个编程语言中流通的数据格式&#xff0c;负责不同编程语言中的数据传递和交互 为了让不同的语言能够相互通…

《LTC与铁三角∶从线索到回款-人民邮电》关于铁三角不错的论述

《LTC与铁三角∶从线索到回款-人民邮电》一书中&#xff0c;关于铁三角不错的论述&#xff0c;收藏之&#xff1a;客户责任人的角色定义及核心价值 AR 的核心价值定位主要体现在三个方面&#xff1a;客户关系、 客户满意度、竞争对手 “ 压制 ” 。 维护客户关系&#x…

百川2模型解读

简介 Baichuan 2是多语言大模型&#xff0c;目前开源了70亿和130亿参数规模的模型。在公开基准如MMLU、CMMLU、GSM8K和HumanEval上的评测&#xff0c;Baichuan 2达到或超过了其他同类开源模型&#xff0c;并在医学和法律等垂直领域表现优异。此外&#xff0c;官方还发布所有预…

[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)

文章涉及具体代码gitee&#xff1a; 登录 - Gitee.com 目录 1.插入排序 1.直接插入排序 总结 2.希尔排序 总结 2.选择排序 1.选择排序 ​编辑 总结 2.堆排序 总结 3.交换排序 1.冒泡排序 总结 2.快速排序 总结 4.归并排序 总结 5.总的分析总结 1.插入排…

Unity---版本控制软件

13.3 版本控制——Git-1_哔哩哔哩_bilibili Git用的比较多 Git 常用Linux命令 pwd&#xff1a;显示当前所在路径 ls&#xff1a;显示当前路径下的所有文件 tab键自动补全 cd&#xff1a;切换路径 mkdir&#xff1a;在当前路径下创建一个文件夹 clear&#xff1a;清屏 vim…

Linux的socket详解

一、本机直接的进程通信方式 管道&#xff08;Pipes&#xff09;&#xff1a; 匿名管道&#xff08;Anonymous pipes&#xff09;&#xff1a;通常用于父子进程间的通信&#xff0c;它是单向的。命名管道&#xff08;Named pipes&#xff0c;也称FIFO&#xff09;&#xff1a;允…

微星主板安装双系统不能进入Ubuntu的解决办法

在微星主板的台式机上面依次安装了Windows11和Ubuntu22.04。在Ubuntu安装完成后重启&#xff0c;没有出现系统选择界面&#xff0c;直接进入了Windows11。怎么解决&#xff1f;方法如下&#xff1a; &#xff08;1&#xff09;正常安装Windows11 &#xff08;2&#xff09;安…

《自动机理论、语言和计算导论》阅读笔记:p352-P401

《自动机理论、语言和计算导论》学习第 12 天&#xff0c;p352-P401总结&#xff0c;总计 50 页。 一、技术总结 1.Turing Machine ™ 2.undecidability ​ a.Ld(the diagonalization language) 3.reduction p392, In general, if we have an algorithm to convert insta…