Skip to content

Commit

Permalink
Merge pull request #10 from azizkayumov/link
Browse files Browse the repository at this point in the history
Link
  • Loading branch information
azizkayumov committed Sep 27, 2023
2 parents 159e55c + 659cb1b commit 24f1f35
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
splay::splay,
};

// constructs a path from the root to the node at idx
// constructs a path from a node to the root of the tree
pub fn access(forest: &mut Vec<Node>, node_idx: usize) {
assert!(node_idx < forest.len(), "access: node_idx out of bounds");
splay(forest, node_idx);
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![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 link;
mod node;
mod splay;
132 changes: 132 additions & 0 deletions src/link.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::{
access::access,
node::{Node, Parent},
};

pub fn link(forest: &mut Vec<Node>, v: usize, w: usize) {
access(forest, v);
access(forest, w);
if !matches!(forest[v].parent, Parent::Root) || v == w {
return; // already connected
}
assert!(forest[w].right.is_none(), "link: w should be a root!");
forest[w].right = Some(v);
forest[v].parent = Parent::Node(w);
}

#[cfg(test)]
mod tests {
use super::link;
use crate::{
connected::connected,
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
super::link(&mut forest, 0, 1);
assert!(connected(&mut forest, 0, 1)); // now connected
}

#[test]
pub fn already_connected() {
// '2' has a right child '3':
// link(0, 3) should add no link, and result in (| denotes a path pointer):
// 0 0 0 3
// / \ / | / | /
// 1 2 => 1 2 => 1 3 => 0
// \ \ / / \
// 3 3 2 1 2
//
let mut forest = create_nodes(4);
forest[0].left = Some(1);
forest[0].right = Some(2);
forest[1].parent = Parent::Node(0);
forest[2].parent = Parent::Node(0);
forest[2].right = Some(3);
forest[3].parent = Parent::Node(2);
link(&mut forest, 0, 3);
assert!(matches!(forest[3].parent, Parent::Root));
assert_eq!(forest[3].left, Some(0));
assert_eq!(forest[3].right, None);
assert!(matches!(forest[0].parent, Parent::Node(3)));
assert_eq!(forest[0].left, Some(1));
assert_eq!(forest[0].right, Some(2));
assert!(matches!(forest[1].parent, Parent::Node(0)));
assert_eq!(forest[1].left, None);
assert_eq!(forest[1].right, None);
assert!(matches!(forest[2].parent, Parent::Node(0)));
assert_eq!(forest[2].left, None);
assert_eq!(forest[2].right, None);
}

#[test]
pub fn already_connected_with_path() {
// '3' has a path pointer to '2', and '2' has a path pointer to '0':
// link(0, 1) should add no link, and result in (| denotes a path pointer):
// 0 0 0 3
// / \ / | / | /
// 1 2 => 1 2 => 1 3 => 0
// | | / / \
// 3 3 2 1 2
//
let mut forest = create_nodes(4);
forest[0].left = Some(1);
forest[0].right = Some(2);
forest[1].parent = Parent::Node(0);
forest[2].parent = Parent::Node(0);
forest[3].parent = Parent::Path(2);
link(&mut forest, 0, 3);
assert!(matches!(forest[3].parent, Parent::Root));
assert_eq!(forest[3].left, Some(0));
assert_eq!(forest[3].right, None);
assert!(matches!(forest[0].parent, Parent::Node(3)));
assert_eq!(forest[0].left, Some(1));
assert_eq!(forest[0].right, Some(2));
assert!(matches!(forest[1].parent, Parent::Node(0)));
assert_eq!(forest[1].left, None);
assert_eq!(forest[1].right, None);
assert!(matches!(forest[2].parent, Parent::Node(0)));
assert_eq!(forest[2].left, None);
assert_eq!(forest[2].right, None);
}

#[test]
pub fn link_to_leftmost() {
// Given two trees:
// 0 3
// / \
// 1 2
// link(1, 3) should result in a single tree (| denotes a path pointer):
// 1 3 1
// | | \
// 0 => 0 3
// \ \
// 2 2
//
let mut forest = create_nodes(4);
forest[0].left = Some(1);
forest[0].right = Some(2);
forest[1].parent = Parent::Node(0);
forest[2].parent = Parent::Node(0);
link(&mut forest, 3, 1);
assert!(matches!(forest[1].parent, Parent::Root));
assert_eq!(forest[1].right, Some(3));
assert_eq!(forest[1].left, None);
assert!(matches!(forest[3].parent, Parent::Node(1)));
assert_eq!(forest[3].right, None);
assert_eq!(forest[3].left, None);
assert!(matches!(forest[0].parent, Parent::Path(1)));
assert_eq!(forest[0].right, Some(2));
assert_eq!(forest[0].left, None);
assert!(matches!(forest[2].parent, Parent::Node(0)));
assert_eq!(forest[2].right, None);
assert_eq!(forest[2].left, None);
}
}

0 comments on commit 24f1f35

Please sign in to comment.