2023-10-20 22:32:43 +00:00
|
|
|
//! 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.
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
use std::{
|
|
|
|
cell::{Ref, RefCell},
|
|
|
|
collections::VecDeque,
|
|
|
|
rc::Rc,
|
|
|
|
};
|
2023-10-20 22:32:43 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
2023-10-21 00:17:33 +00:00
|
|
|
pub enum Tree<T> {
|
2023-10-20 22:32:43 +00:00
|
|
|
Empty,
|
2023-10-20 23:49:31 +00:00
|
|
|
Root(Node<T>),
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
impl<T> Default for Tree<T> {
|
2023-10-20 22:32:43 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Tree::Empty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
impl<T> Tree<T> {
|
2023-10-20 22:32:43 +00:00
|
|
|
pub fn set_value(&mut self, value: T) {
|
2023-10-20 23:49:31 +00:00
|
|
|
*self = Tree::Root(Node::new(value));
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-20 23:49:31 +00:00
|
|
|
/// Use a breadth-first-search pattern to find a node, returning the node if found.
|
|
|
|
pub fn find_bfs<'a, F>(&'a self, op: F) -> Option<Node<T>>
|
2023-10-20 22:32:43 +00:00
|
|
|
where
|
|
|
|
F: FnOnce(&T) -> bool + Copy,
|
|
|
|
{
|
2023-10-20 23:49:31 +00:00
|
|
|
let mut queue: VecDeque<Node<T>> = match self {
|
2023-10-20 22:32:43 +00:00
|
|
|
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() {
|
2023-10-20 23:49:31 +00:00
|
|
|
if op(&node.value()) {
|
2023-10-20 22:32:43 +00:00
|
|
|
return Some(node.clone());
|
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
for child in node.children().iter() {
|
2023-10-20 23:49:31 +00:00
|
|
|
queue.push_back(child.clone())
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-20 23:49:31 +00:00
|
|
|
// By using the Rc<RefCell> container here, I'm able to make Node easily clonable while still
|
|
|
|
// having the contents be shared. This means that I can change the tree structure without having to
|
|
|
|
// make the visible objects mutable.
|
|
|
|
//
|
|
|
|
// This feels like cheating the type system.
|
2023-10-21 00:17:33 +00:00
|
|
|
//
|
|
|
|
// However, since I've moved the RefCell inside of the node, I can borrow the node multiple times
|
|
|
|
// in a traversal function and I can make changes to nodes that I find.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Node<T>(Rc<RefCell<Node_<T>>>);
|
|
|
|
|
|
|
|
impl<T> Clone for Node<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Node(Rc::clone(&self.0))
|
|
|
|
}
|
|
|
|
}
|
2023-10-20 23:49:31 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
2023-10-21 00:17:33 +00:00
|
|
|
struct Node_<T> {
|
2023-10-20 22:32:43 +00:00
|
|
|
value: T,
|
2023-10-20 23:49:31 +00:00
|
|
|
children: Vec<Node<T>>,
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
impl<T> Node<T> {
|
2023-10-20 22:32:43 +00:00
|
|
|
pub fn new(value: T) -> Self {
|
2023-10-20 23:49:31 +00:00
|
|
|
Self(Rc::new(RefCell::new(Node_ {
|
2023-10-20 22:32:43 +00:00
|
|
|
value,
|
|
|
|
children: vec![],
|
2023-10-20 23:49:31 +00:00
|
|
|
})))
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
// I am copying the value because I don't have a mechanism for keeping the borrow ref active.
|
|
|
|
// My next step is to figure out how to keep the borrow ref active so that I don't have to
|
|
|
|
// clone the item. Then I could drop the Clone constraint.
|
|
|
|
pub fn value<'a>(&'a self) -> Ref<T> {
|
|
|
|
Ref::map(self.0.borrow(), |v| &v.value)
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
pub fn children<'a>(&'a self) -> Ref<Vec<Node<T>>> {
|
|
|
|
Ref::map(self.0.borrow(), |v| &v.children)
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-20 23:49:31 +00:00
|
|
|
pub fn add_child_node(&self, child: Node<T>) {
|
|
|
|
self.0.borrow_mut().children.push(child)
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
|
2023-10-20 23:49:31 +00:00
|
|
|
pub fn add_child_value(&self, value: T) {
|
|
|
|
self.0.borrow_mut().children.push(Node::new(value))
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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());
|
|
|
|
|
2023-10-20 23:49:31 +00:00
|
|
|
let node = tree.find_bfs(|val| *val == 15).unwrap();
|
|
|
|
node.add_child_value(20);
|
2023-10-20 22:32:43 +00:00
|
|
|
|
|
|
|
assert!(tree.find_bfs(|val| *val == 20).is_some());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn node_can_add_children() {
|
2023-10-20 23:49:31 +00:00
|
|
|
let n = Node::new(15);
|
2023-10-20 22:32:43 +00:00
|
|
|
n.add_child_value(20);
|
|
|
|
|
2023-10-21 00:17:33 +00:00
|
|
|
assert_eq!(*n.value(), 15);
|
2023-10-20 23:49:31 +00:00
|
|
|
// assert_eq!(n.children(), vec![Rc::new(RefCell::new(Node::new(20)))]);
|
2023-10-20 22:32:43 +00:00
|
|
|
}
|
|
|
|
}
|