From 21c8293db6270bd3656775a0ca7dfa9d9c297159 Mon Sep 17 00:00:00 2001 From: bsbds <69835502+bsbds@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:02:01 +0800 Subject: [PATCH] refactor: use breadth-first search in find all overlap in interval tree Signed-off-by: bsbds <69835502+bsbds@users.noreply.github.com> --- crates/utils/src/interval_map/mod.rs | 37 +++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/crates/utils/src/interval_map/mod.rs b/crates/utils/src/interval_map/mod.rs index 030eaea13..16ba372d2 100644 --- a/crates/utils/src/interval_map/mod.rs +++ b/crates/utils/src/interval_map/mod.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; + use petgraph::graph::{DefaultIx, IndexType, NodeIndex}; #[cfg(test)] @@ -79,7 +81,7 @@ where if self.node_ref(self.root, Node::is_sentinel) { Vec::new() } else { - self.find_all_overlap_inner(self.root, interval) + self.find_all_overlap_inner_unordered(self.root, interval) } } @@ -289,6 +291,7 @@ where } /// Finds all intervals in the map that overlaps with the given interval. + #[cfg(interval_tree_find_overlap_ordered)] fn find_all_overlap_inner( &self, x: NodeIndex, @@ -311,6 +314,38 @@ where list } + /// Finds all intervals in the map that overlaps with the given interval. + /// + /// The result is unordered because of breadth-first search to save stack size + fn find_all_overlap_inner_unordered( + &self, + x: NodeIndex, + interval: &Interval, + ) -> Vec<(&Interval, &V)> { + let mut list = Vec::new(); + let mut queue = VecDeque::new(); + queue.push_back(x); + while let Some(p) = queue.pop_front() { + if self.node_ref(p, Node::interval).overlap(interval) { + list.push(self.node_ref(p, |np| (np.interval(), np.value()))); + } + let p_left = self.node_ref(p, Node::left); + let p_right = self.node_ref(p, Node::right); + if self.max(p_left) >= Some(&interval.low) { + queue.push_back(p_left); + } + if self + .max(self.node_ref(p, Node::right)) + .map(|rmax| IntervalRef::new(&self.node_ref(p, Node::interval).low, rmax)) + .is_some_and(|i| i.overlap(interval)) + { + queue.push_back(p_right); + } + } + + list + } + /// Search for an interval that overlaps with the given interval. fn search(&self, interval: &Interval) -> NodeIndex { let mut x = self.root;