#map #library #interval-tree #data

nightly 离散_范围_map

此包提供了 DiscreteRangeMap 和 DiscreteRangeSet,用于存储基于 BTreeMap 的非重叠离散区间数据结构。

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数据结构

Download history 26/week @ 2024-03-08 11/week @ 2024-03-15 47/week @ 2024-03-29 14/week @ 2024-04-05

每月107 次下载
用于 gap_query_interval_tree

AGPL-3.0-or-later

105KB
2K SLoC

discrete_range_map

License Docs Maintained Crates.io

discrete_range_map_logo

此包已重命名为 nodit

大约在 2024-01-03 的版本 v0.7.0 中,此包从 discrete_range_map 重命名为 nodit,因为旧名称不准确。请切换到 nodit 包,因为此包将不再接收更新。

旧 Readme

此包提供了 DiscreteRangeMapDiscreteRangeSet,基于 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被认为是有效的,因为它包含值45,然而,4..4被认为是无效的,因为它不包含任何值。另一个无效范围的例子是起始值大于结束值的情况,例如5..2100..=40

以下是几个范围及其有效性的示例

范围 有效
0..=0
0..0
0..1
9..8
(Bound::Exluded(3), Bound::Exluded(4))
400..=400

重叠

如果有这样一个点,它同时包含在两个范围之内,则两个范围是“重叠”的。

接触

两个范围“接触”是指它们不相交,并且它们之间没有值。例如,2..44..6 是接触的,但 2..46..8 不是,同样 2..64..8 也不是。

合并

当一个范围“合并”其他范围时,它会吸收它们以变得更大。

进一步阅读

请参阅维基百科关于数学区间的文章:[https://en.wikipedia.org/wiki/Interval_(mathematics)](https://en.wikipedia.org/wiki/Interval_(mathematics))

特性

此crate目前没有任何特性。

致谢

我最初独立想出了 StartBoundOrd bodge,然而,后来我偶然发现了 rangemap,它也使用了 StartBoundOrd bodge。 rangemap 然后成为我的主要灵感来源。

后来我取消了 Ord bodge,并切换到我自己完整的 BTreeMap 版本,它受到了 copse 的启发和分支,因为它增加了灵活性。

起源

这个库的目标是成为一个比 rangemap 更通用的超集,源于 这个问题这个拉取请求,我在其中将 rangemapRangeMap 更改为使用 RangeBounds 作为键,在我意识到从头开始编写可能更容易和更简单之后。

然而,值得注意的是,该库最终从其起源扩展和演变。

此crate之前命名为 range_bounds_map

类似crate

在搜索相关主题时,我发现了一些相关的crate

nodit https://docs.rs/nodit

依赖项

~1.3–2MB
~41K SLoC