11 个版本
0.6.3 | 2024年1月5日 |
---|---|
0.6.2 | 2023年12月26日 |
0.5.2 | 2023年10月11日 |
0.5.1 | 2023年7月1日 |
0.4.0 | 2023年4月24日 |
#1466 在 数据结构
每月107 次下载
用于 gap_query_interval_tree
105KB
2K SLoC
discrete_range_map
此包已重命名为 nodit
大约在 2024-01-03 的版本 v0.7.0
中,此包从 discrete_range_map
重命名为 nodit
,因为旧名称不准确。请切换到 nodit
包,因为此包将不再接收更新。
旧 Readme
此包提供了 DiscreteRangeMap
和 DiscreteRangeSet
,基于 BTreeMap
的用于存储非重叠离散区间的数据结构。
no_std
支持,并且应与默认功能一起工作。
必须实现 Copy
由于与非 Copy
类型的实现复杂性,当前数据结构要求范围类型以及这些范围覆盖的点必须是 Copy
。
使用包含-排除范围示例
use discrete_range_map::test_ranges::ie;
use discrete_range_map::DiscreteRangeMap;
let mut map = DiscreteRangeMap::new();
map.insert_strict(ie(0, 5), true);
map.insert_strict(ie(5, 10), false);
assert_eq!(map.overlaps(ie(-2, 12)), true);
assert_eq!(map.contains_point(20), false);
assert_eq!(map.contains_point(5), true);
使用自定义范围类型示例
use std::ops::{Bound, RangeBounds};
use discrete_range_map::test_ranges::ie;
use discrete_range_map::{
DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
InclusiveRange,
};
#[derive(Debug, Copy, Clone)]
enum Reservation {
// Start, End (Inclusive-Inclusive)
Finite(i8, i8),
// Start (Inclusive-Infinity)
Infinite(i8),
}
// First, we need to implement InclusiveRange
impl InclusiveRange<i8> for Reservation {
fn start(&self) -> i8 {
match self {
Reservation::Finite(start, _) => *start,
Reservation::Infinite(start) => *start,
}
}
fn end(&self) -> i8 {
match self {
Reservation::Finite(_, end) => *end,
Reservation::Infinite(_) => i8::MAX,
}
}
}
// Second, we need to implement From<InclusiveInterval<i8>>
impl From<InclusiveInterval<i8>> for Reservation {
fn from(value: InclusiveInterval<i8>) -> Self {
if value.end == i8::MAX {
Reservation::Infinite(value.start)
} else {
Reservation::Finite(
value.start,
value.end.up().unwrap(),
)
}
}
}
// Next we can create a custom typed DiscreteRangeMap
let reservation_map = DiscreteRangeMap::from_slice_strict([
(Reservation::Finite(10, 20), "Ferris".to_string()),
(Reservation::Infinite(21), "Corro".to_string()),
])
.unwrap();
for (reservation, name) in reservation_map.overlapping(ie(16, 17))
{
println!(
"{name} has reserved {reservation:?} inside the range 16..17"
);
}
for (reservation, name) in reservation_map.iter() {
println!("{name} has reserved {reservation:?}");
}
assert_eq!(
reservation_map.overlaps(Reservation::Infinite(0)),
true
);
关键理解和哲学
离散性
此包旨在与 Discrete
类型一起工作,而不是与 Continuous
类型。例如,u8
是一个 Discrete
类型,但如果你尝试将其解析为十进制值,则 String
是一个 Continuous
。
原因在于,常见的区间-数学
运算取决于底层类型是离散
还是连续
。例如,5..=6
触及了7..=8
,因为整数是离散
的,但5.0..=6.0
并没有触及7.0..=8.0
,因为存在值6.5
。
有限性
该库还设计用于与有限
类型一起工作,因为它更容易实现,并且对用户没有限制,因为您仍然可以使用实在无限
的概念,以矛盾的方式在有限
类型中表示无限
数字。
例如,您可以为u8
定义无限
为u8::MAX
,或者如果您仍然想将u8::MAX
作为一个有限
数字,您可以定义一个包装类型,为u8
添加一个实在无限
值到u8
集合。
无效范围
在此库中,并非所有范围都被视为有效范围。在此库中使用范围的定义是,只有当范围包含底层域至少一个值时,该范围才是有效的。
例如,4..6
被认为是有效的,因为它包含值4
和5
,然而,4..4
被认为是无效的,因为它不包含任何值。另一个无效范围的例子是起始值大于结束值的情况,例如5..2
或100..=40
。
以下是几个范围及其有效性的示例
范围 | 有效 |
---|---|
0..=0 | 是 |
0..0 | 否 |
0..1 | 是 |
9..8 | 否 |
(Bound::Exluded(3), Bound::Exluded(4)) | 否 |
400..=400 | 是 |
重叠
如果有这样一个点,它同时包含在两个范围之内,则两个范围是“重叠”的。
接触
两个范围“接触”是指它们不相交,并且它们之间没有值。例如,2..4
和 4..6
是接触的,但 2..4
和 6..8
不是,同样 2..6
和 4..8
也不是。
合并
当一个范围“合并”其他范围时,它会吸收它们以变得更大。
进一步阅读
请参阅维基百科关于数学区间的文章:[https://en.wikipedia.org/wiki/Interval_(mathematics)](https://en.wikipedia.org/wiki/Interval_(mathematics))
特性
此crate目前没有任何特性。
致谢
我最初独立想出了 StartBound
: Ord
bodge,然而,后来我偶然发现了 rangemap
,它也使用了 StartBound
: Ord
bodge。 rangemap
然后成为我的主要灵感来源。
后来我取消了 Ord
bodge,并切换到我自己完整的 BTreeMap
版本,它受到了 copse
的启发和分支,因为它增加了灵活性。
起源
这个库的目标是成为一个比 rangemap
更通用的超集,源于 这个问题 和 这个拉取请求,我在其中将 rangemap
的 RangeMap
更改为使用 RangeBounds
作为键,在我意识到从头开始编写可能更容易和更简单之后。
然而,值得注意的是,该库最终从其起源扩展和演变。
此crate之前命名为 range_bounds_map
。
类似crate
在搜索相关主题时,我发现了一些相关的crate
- https://docs.rs/rangemap 与此crate非常相似,但只能使用
Range
和RangeInclusive
作为其map
和set
结构体(分别)的键。 - https://docs.rs/btree-range-map
- https://docs.rs/ranges 一个用于完全泛型范围的酷库(与std::ops ranges不同),以及用于存储它们的
Ranges
数据结构(遗憾的是基于Vec) - https://docs.rs/intervaltree 允许重叠区间,但遗憾的是不可变
- https://docs.rs/nonoverlapping_interval_tree 与 rangemap 非常相似,但没有
gaps()
函数,并且仅适用于Range
而不是RangeInclusive
。而且也没有复杂的合并函数。 - https://docs.rs/unbounded-interval-tree 基于一篇 2007 年发表的论文的数据结构!它支持任何范围作为键,但遗憾的是,它实现了一个基于非平衡的
Box<Node>
的树,但它也支持重叠区间,而我自己的库不支持。 - https://docs.rs/rangetree 我并不完全清楚这个库是什么或不是什么,但它看起来是一个用于 Range Tree 的自定义红黑树/BTree 实现。有趣但也很老(5 年)且使用 unsafe。
依赖项
~1.3–2MB
~41K SLoC