diff --git a/src/lib.rs b/src/lib.rs index dc50993..a74cd1e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,12 +2,9 @@ mod node; mod path; mod splay; - -use splay::update_max; - use crate::{ node::{Node, Parent}, - splay::splay, + splay::{splay, update_max}, }; pub struct LinkCutTree { @@ -21,6 +18,10 @@ impl LinkCutTree { Self { forest: nodes } } + pub fn set_weight(&mut self, v: usize, weight: f64) { + self.forest[v].weight = weight; + } + // Constructs a path from a node to the root of the tree. pub fn access(&mut self, v: usize) { splay(&mut self.forest, v); @@ -88,7 +89,6 @@ impl LinkCutTree { #[cfg(test)] mod tests { use crate::node::Parent; - use rand::{seq::SliceRandom, Rng, SeedableRng}; #[test] pub fn access_base_case() { @@ -443,49 +443,4 @@ mod tests { assert_eq!(lctree.findmax(1), 0); assert_eq!(lctree.findmax(0), 0); } - - fn create_random_tree(n: usize, seed: u64) -> (Vec<(usize, usize)>, Vec, Vec) { - let mut rng = rand::rngs::StdRng::seed_from_u64(seed); - - let mut edges = Vec::new(); - let mut weights: Vec = (0..n).map(|i| i as f64).collect(); - weights.shuffle(&mut rng); - - let mut ground_truth = vec![0; n]; - let mut in_tree = Vec::from([0]); - for i in 1..n { - let parent_idx = rng.gen_range(0..in_tree.len()); - let parent = in_tree[parent_idx]; - edges.push((i, parent)); - - ground_truth[i] = if weights[i] > weights[ground_truth[parent]] { - i - } else { - ground_truth[parent] - }; - in_tree.push(i); - } - - (edges, weights, ground_truth) - } - - #[test] - pub fn findmax_random() { - let n = 100; - let seed = rand::thread_rng().gen(); - let (edges, weights, ground_truth) = create_random_tree(n, seed); - let mut lctree = super::LinkCutTree::new(n); - for i in 0..n { - lctree.forest[i].weight = weights[i]; - } - - for (v, w) in edges { - lctree.link(v, w); - } - - for _ in 0..n * 100 { - let v = rand::thread_rng().gen_range(0..n); - assert_eq!(lctree.findmax(v), ground_truth[v]); - } - } } diff --git a/src/node.rs b/src/node.rs index 6b3585c..f9eb7e4 100644 --- a/src/node.rs +++ b/src/node.rs @@ -36,8 +36,8 @@ impl Node { Parent::Root => "Root".to_string(), }; format!( - "Node {{ idx: {}, left: {:?}, right: {:?}, parent: {:?}, max_weight_idx: {} }}", - self.idx, self.left, self.right, parent, self.max_weight_idx + "Node {{ idx: {}, left: {:?}, right: {:?}, parent: {parent:?}, max_weight_idx: {} }}", + self.idx, self.left, self.right, self.max_weight_idx ) } } diff --git a/tests/test_findmax_random.rs b/tests/test_findmax_random.rs new file mode 100644 index 0000000..efeab71 --- /dev/null +++ b/tests/test_findmax_random.rs @@ -0,0 +1,47 @@ +use lctree::LinkCutTree; +use rand::{seq::SliceRandom, Rng, SeedableRng}; + +fn create_random_tree(n: usize, seed: u64) -> (Vec<(usize, usize)>, Vec, Vec) { + let mut rng = rand::rngs::StdRng::seed_from_u64(seed); + + let mut edges = Vec::new(); + let mut weights: Vec = (0..n).map(|i| i as f64).collect(); + weights.shuffle(&mut rng); + + let mut max_to_root = vec![0; n]; + let mut in_tree = Vec::from([0]); + for i in 1..n { + let parent_idx = rng.gen_range(0..in_tree.len()); + let parent = in_tree[parent_idx]; + edges.push((i, parent)); + + max_to_root[i] = if weights[i] > weights[max_to_root[parent]] { + i + } else { + max_to_root[parent] + }; + in_tree.push(i); + } + + (edges, weights, max_to_root) +} + +#[test] +pub fn findmax_random() { + let n = 100; + let seed = rand::thread_rng().gen(); + let (edges, weights, max_to_root) = create_random_tree(n, seed); + let mut lctree = LinkCutTree::new(n); + for i in 0..n { + lctree.set_weight(i, weights[i]); + } + + for (v, w) in edges { + lctree.link(v, w); + } + + for _ in 0..n * 100 { + let v = rand::thread_rng().gen_range(0..n); + assert_eq!(lctree.findmax(v), max_to_root[v]); + } +}