Build a basic tree and experiment with traversals
This commit is contained in:
parent
4114874156
commit
52f814e663
|
@ -4060,6 +4060,10 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tree"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|
|
@ -20,4 +20,5 @@ members = [
|
||||||
"result-extended",
|
"result-extended",
|
||||||
"screenplay",
|
"screenplay",
|
||||||
"sgf",
|
"sgf",
|
||||||
|
"tree",
|
||||||
]
|
]
|
||||||
|
|
1
build.sh
1
build.sh
|
@ -23,6 +23,7 @@ RUST_ALL_TARGETS=(
|
||||||
"result-extended"
|
"result-extended"
|
||||||
"screenplay"
|
"screenplay"
|
||||||
"sgf"
|
"sgf"
|
||||||
|
"tree"
|
||||||
)
|
)
|
||||||
|
|
||||||
build_rust_targets() {
|
build_rust_targets() {
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "tree"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,113 @@
|
||||||
|
//! This data structure is a generic tree which can contain any data. That data itself need to keep
|
||||||
|
//! track of its own tree structure.
|
||||||
|
//!
|
||||||
|
//! This surely already exists. I am created it to test my own ability to do things in Rust.
|
||||||
|
|
||||||
|
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Tree<T> {
|
||||||
|
Empty,
|
||||||
|
Root(Rc<RefCell<Node<T>>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Tree<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Tree::Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Tree<T> {
|
||||||
|
pub fn set_value(&mut self, value: T) {
|
||||||
|
*self = Tree::Root(Rc::new(RefCell::new(Node::new(value))));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_bfs<'a, F>(&'a self, op: F) -> Option<Rc<RefCell<Node<T>>>>
|
||||||
|
where
|
||||||
|
F: FnOnce(&T) -> bool + Copy,
|
||||||
|
{
|
||||||
|
let mut queue: VecDeque<Rc<RefCell<Node<T>>>> = match self {
|
||||||
|
Tree::Empty => VecDeque::new(),
|
||||||
|
Tree::Root(node) => {
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back(node.clone());
|
||||||
|
queue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(node) = queue.pop_front() {
|
||||||
|
if op(&node.borrow().value) {
|
||||||
|
return Some(node.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for child in node.borrow().children.iter() {
|
||||||
|
queue.push_back(child.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Node<T> {
|
||||||
|
value: T,
|
||||||
|
children: Vec<Rc<RefCell<Node<T>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Node<T> {
|
||||||
|
pub fn new(value: T) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
children: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn children<'a>(&'a self) -> &'a Vec<Rc<RefCell<Node<T>>>> {
|
||||||
|
&self.children
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value<'a>(&'a self) -> &'a T {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value_mut<'a>(&'a mut self) -> &'a mut T {
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_child_node(&mut self, child: Node<T>) {
|
||||||
|
self.children.push(Rc::new(RefCell::new(child)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_child_value(&mut self, value: T) {
|
||||||
|
self.children.push(Rc::new(RefCell::new(Node::new(value))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_find_node_in_tree() {
|
||||||
|
let mut tree = Tree::default();
|
||||||
|
tree.set_value(15);
|
||||||
|
assert!(tree.find_bfs(|val| *val == 15).is_some());
|
||||||
|
assert!(tree.find_bfs(|val| *val == 16).is_none());
|
||||||
|
|
||||||
|
{
|
||||||
|
let node_ref = tree.find_bfs(|val| *val == 15).unwrap();
|
||||||
|
node_ref.borrow_mut().add_child_value(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(tree.find_bfs(|val| *val == 20).is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn node_can_add_children() {
|
||||||
|
let mut n = Node::new(15);
|
||||||
|
n.add_child_value(20);
|
||||||
|
|
||||||
|
assert_eq!(n.value, 15);
|
||||||
|
assert_eq!(n.children, vec![Rc::new(RefCell::new(Node::new(20)))]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue