use crate::{NIL, Treap};
pub enum RangeBound<'a, K> {
Unbounded,
Inclusive(&'a K),
Exclusive(&'a K),
}
impl<K: Ord, V> Treap<K, V> {
pub fn range<'a>(
&'a self,
from: RangeBound<'a, K>,
to: RangeBound<'a, K>,
) -> RangeIter<'a, K, V> {
let mut iter = RangeIter {
treap: self,
stack: Vec::new(),
to,
};
iter.descend_to_lower_bound(self.root, &from);
iter
}
}
pub struct RangeIter<'a, K, V> {
treap: &'a Treap<K, V>,
stack: Vec<u32>,
to: RangeBound<'a, K>,
}
impl<'a, K: Ord, V> RangeIter<'a, K, V> {
fn descend_to_lower_bound(&mut self, mut idx: u32, from: &RangeBound<'a, K>) {
while idx != NIL {
let node = &self.treap.nodes[idx as usize];
let take_left = match from {
RangeBound::Unbounded => true,
RangeBound::Inclusive(k) => &*node.key >= *k,
RangeBound::Exclusive(k) => &*node.key > *k,
};
if take_left {
self.stack.push(idx);
idx = node.left;
} else {
idx = node.right;
}
}
}
fn in_upper_bound(&self, key: &K) -> bool {
match &self.to {
RangeBound::Unbounded => true,
RangeBound::Inclusive(k) => key <= k,
RangeBound::Exclusive(k) => key < k,
}
}
}
impl<'a, K: Ord, V> Iterator for RangeIter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
let idx = self.stack.pop()?;
let node = &self.treap.nodes[idx as usize];
if !self.in_upper_bound(&node.key) {
self.stack.clear();
return None;
}
let mut right = node.right;
while right != NIL {
self.stack.push(right);
right = self.treap.nodes[right as usize].left;
}
Some((&node.key, &node.value))
}
}
#[cfg(test)]
#[path = "range_tests.rs"]
mod tests;