Move the refcell to inside of the Node
This commit is contained in:
parent
52f814e663
commit
fbf6a9e76e
|
@ -6,27 +6,28 @@
|
||||||
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Tree<T> {
|
pub enum Tree<T: Clone> {
|
||||||
Empty,
|
Empty,
|
||||||
Root(Rc<RefCell<Node<T>>>),
|
Root(Node<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for Tree<T> {
|
impl<T: Clone> Default for Tree<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Tree::Empty
|
Tree::Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tree<T> {
|
impl<T: Clone> Tree<T> {
|
||||||
pub fn set_value(&mut self, value: T) {
|
pub fn set_value(&mut self, value: T) {
|
||||||
*self = Tree::Root(Rc::new(RefCell::new(Node::new(value))));
|
*self = Tree::Root(Node::new(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_bfs<'a, F>(&'a self, op: F) -> Option<Rc<RefCell<Node<T>>>>
|
/// 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>>
|
||||||
where
|
where
|
||||||
F: FnOnce(&T) -> bool + Copy,
|
F: FnOnce(&T) -> bool + Copy,
|
||||||
{
|
{
|
||||||
let mut queue: VecDeque<Rc<RefCell<Node<T>>>> = match self {
|
let mut queue: VecDeque<Node<T>> = match self {
|
||||||
Tree::Empty => VecDeque::new(),
|
Tree::Empty => VecDeque::new(),
|
||||||
Tree::Root(node) => {
|
Tree::Root(node) => {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
|
@ -36,50 +37,54 @@ impl<T> Tree<T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(node) = queue.pop_front() {
|
while let Some(node) = queue.pop_front() {
|
||||||
if op(&node.borrow().value) {
|
if op(&node.value()) {
|
||||||
return Some(node.clone());
|
return Some(node.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for child in node.borrow().children.iter() {
|
for child in node.children() {
|
||||||
queue.push_back(child.clone());
|
queue.push_back(child.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
// By using the Rc<RefCell> container here, I'm able to make Node easily clonable while still
|
||||||
pub struct Node<T> {
|
// 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.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Node<T: Clone>(Rc<RefCell<Node_<T>>>);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Node_<T: Clone> {
|
||||||
value: T,
|
value: T,
|
||||||
children: Vec<Rc<RefCell<Node<T>>>>,
|
children: Vec<Node<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Node<T> {
|
impl<T: Clone> Node<T> {
|
||||||
pub fn new(value: T) -> Self {
|
pub fn new(value: T) -> Self {
|
||||||
Self {
|
Self(Rc::new(RefCell::new(Node_ {
|
||||||
value,
|
value,
|
||||||
children: vec![],
|
children: vec![],
|
||||||
}
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn children<'a>(&'a self) -> &'a Vec<Rc<RefCell<Node<T>>>> {
|
pub fn value<'a>(&'a self) -> T {
|
||||||
&self.children
|
self.0.borrow().value.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value<'a>(&'a self) -> &'a T {
|
pub fn children<'a>(&'a self) -> Vec<Node<T>> {
|
||||||
&self.value
|
self.0.borrow().children.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_mut<'a>(&'a mut self) -> &'a mut T {
|
pub fn add_child_node(&self, child: Node<T>) {
|
||||||
&mut self.value
|
self.0.borrow_mut().children.push(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_child_node(&mut self, child: Node<T>) {
|
pub fn add_child_value(&self, value: T) {
|
||||||
self.children.push(Rc::new(RefCell::new(child)));
|
self.0.borrow_mut().children.push(Node::new(value))
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_child_value(&mut self, value: T) {
|
|
||||||
self.children.push(Rc::new(RefCell::new(Node::new(value))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,20 +99,18 @@ mod tests {
|
||||||
assert!(tree.find_bfs(|val| *val == 15).is_some());
|
assert!(tree.find_bfs(|val| *val == 15).is_some());
|
||||||
assert!(tree.find_bfs(|val| *val == 16).is_none());
|
assert!(tree.find_bfs(|val| *val == 16).is_none());
|
||||||
|
|
||||||
{
|
let node = tree.find_bfs(|val| *val == 15).unwrap();
|
||||||
let node_ref = tree.find_bfs(|val| *val == 15).unwrap();
|
node.add_child_value(20);
|
||||||
node_ref.borrow_mut().add_child_value(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(tree.find_bfs(|val| *val == 20).is_some());
|
assert!(tree.find_bfs(|val| *val == 20).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn node_can_add_children() {
|
fn node_can_add_children() {
|
||||||
let mut n = Node::new(15);
|
let n = Node::new(15);
|
||||||
n.add_child_value(20);
|
n.add_child_value(20);
|
||||||
|
|
||||||
assert_eq!(n.value, 15);
|
assert_eq!(n.value(), 15);
|
||||||
assert_eq!(n.children, vec![Rc::new(RefCell::new(Node::new(20)))]);
|
// assert_eq!(n.children(), vec![Rc::new(RefCell::new(Node::new(20)))]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue