Skip to content

Commit

Permalink
Merge pull request #11 from azizkayumov/cut
Browse files Browse the repository at this point in the history
Cut
  • Loading branch information
azizkayumov committed Sep 28, 2023
2 parents 24f1f35 + dfa2157 commit dee2486
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/connected.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn connected(forest: &mut Vec<Node>, v: usize, w: usize) -> bool {
);
access(forest, v); // v is now the root of the tree
access(forest, w);
// if v is not the root of the tree anymore, then v and w are connected:
// if access(w) messed with the root of the tree, then v and w are connected:
!matches!(forest[v].parent, Parent::Root) || v == w
}

Expand Down
94 changes: 94 additions & 0 deletions src/cut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::{
access::access,
node::{Node, Parent},
};

pub fn cut(forest: &mut Vec<Node>, v: usize) {
self::access(forest, v);
if let Some(left) = forest[v].left {
forest[left].parent = Parent::Root;
forest[v].left = None;
}
}

#[cfg(test)]
mod tests {
use crate::{
connected::connected,
cut::cut,
link::link,
node::{Node, Parent},
};

fn create_nodes(n: usize) -> Vec<Node> {
(0..n).map(|i| Node::new(i, 0.0)).collect()
}

#[test]
pub fn base_case() {
let mut forest = create_nodes(2);
assert!(!connected(&mut forest, 0, 1)); // not connected yet

link(&mut forest, 0, 1);
assert!(matches!(forest[1].parent, Parent::Root));
assert_eq!(forest[1].right, Some(0));
assert_eq!(forest[1].left, None);
assert!(matches!(forest[0].parent, Parent::Node(1)));
// 1
// \ <= link(0, 1)
// 0

assert!(connected(&mut forest, 0, 1)); // now connected
assert!(matches!(forest[1].parent, Parent::Root));
assert_eq!(forest[1].right, None);
assert_eq!(forest[1].left, None);
assert!(matches!(forest[0].parent, Parent::Path(1)));
// 0 1
// / => |
// 1 0

super::cut(&mut forest, 0);
assert!(matches!(forest[0].parent, Parent::Root));
assert_eq!(forest[0].right, None);
// 0 0
// / =>
// 1 1
assert!(!connected(&mut forest, 0, 1)); // now disconnected
}

#[test]
pub fn cut_into_two_subtrees() {
let mut forest = create_nodes(5);
forest[0].left = Some(1);
forest[1].parent = Parent::Node(0);
forest[1].left = Some(2);
forest[2].parent = Parent::Node(1);
forest[3].right = Some(4);
forest[4].parent = Parent::Node(3);
// Given two trees:
// 0 3
// / \
// 1 4
// /
// 2
link(&mut forest, 2, 3);
// link(2, 3) should result in:
// 3
// | \
// 4 2
// |
// 1
// \
// 0
assert!(matches!(forest[3].parent, Parent::Root));
assert!(matches!(forest[4].parent, Parent::Path(3)));
assert_eq!(forest[3].right, Some(2));
assert!(matches!(forest[2].parent, Parent::Node(3)));
assert!(matches!(forest[1].parent, Parent::Path(2)));
assert_eq!(forest[1].right, Some(0));
assert!(connected(&mut forest, 2, 3));
cut(&mut forest, 2);
assert!(!connected(&mut forest, 2, 3));
assert!(!connected(&mut forest, 2, 4));
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(dead_code, clippy::module_name_repetitions)] // yes, I want to name my structs with the same name as the file
mod access;
mod connected;
mod cut;
mod link;
mod node;
mod splay;

0 comments on commit dee2486

Please sign in to comment.