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