use super::searching::{ST, OrderedST};
use super::searching::binary_search_tree::{BST, Node};
pub mod kd_tree;
pub mod interval_search_tree;
pub trait RangeSearch1D<K, V>: OrderedST<K, V> {
fn insert(&mut self, key: K, val: V);
fn range_search(&self, key1: &K, key2: &K) -> Option<Vec<&K>>;
fn range_count(&self, key1: &K, key2: &K) -> usize;
}
pub trait OrthogonalRangeSearch2D<K, V>: OrderedST<(K,K), V> {
fn insert(&mut self, key: (K,K), val: V);
fn range_search(&self, left_top: (K,K), right_bottom: (K,K)) -> Option<Vec<&(K,K)>>;
fn range_count(&self, left_top: (K,K), right_bottom: (K,K)) -> usize;
}
impl<K: PartialOrd, V> RangeSearch1D<K, V> for BST<K, V> {
#[inline]
fn insert(&mut self, key: K, val: V) {
self.put(key, val);
}
fn range_search(&self, lo: &K, hi: &K) -> Option<Vec<&K>> {
let mut queue: Vec<&K> = Vec::new();
fn inorder<'a, K: PartialOrd, V>(x: Option<&'a Box<Node<K,V>>>, queue: &mut Vec<&'a K>, lo: &K, hi: &K) {
if x.is_none() {
return;
}
x.map(|n| inorder(n.left.as_ref(), queue, lo, hi));
if x.map(|n| n.key >= *lo && n.key <= *hi ).unwrap_or(false) {
x.map(|n| queue.push(&n.key));
}
x.map(|n| inorder(n.right.as_ref(), queue, lo, hi));
};
inorder(self.root.as_ref(), &mut queue, lo, hi);
if queue.is_empty() {
None
} else {
Some(queue)
}
}
fn range_count(&self, lo: &K, hi: &K) -> usize {
if self.contains(hi) {
self.rank(hi) - self.rank(lo) + 1
} else {
self.rank(hi) - self.rank(lo)
}
}
}
#[test]
fn test_range_range_search_1d() {
let mut ost = BST::<char,()>::new();
ost.insert('B', ());
ost.insert('D', ());
ost.insert('A', ());
ost.insert('I', ());
ost.insert('H', ());
ost.insert('F', ());
ost.insert('P', ());
assert_eq!(ost.range_count(&'G', &'K'), 2);
assert_eq!(ost.range_search(&'G', &'K'), Some(vec![&'H', &'I']));
assert_eq!(ost.range_search(&'Y', &'Z'), None);
}