use std::fmt::Display; /// A binary tree structure used to parse and evaluate an expression into RPN. /// /// Work in progress. /// /// Type parameter must implement `Copy` trait until borrowing is implemented. pub struct Tree { pub root_node: TreeNode, } impl Tree { /// Takes reducer function input with following signature. /// /// The caller should ensure that reducer function returns same type as /// the left- and right-hand side. /// /// Example: adding LHS: , Parent: , RHS: to sum values in tree. pub fn reduce(&self, reducer: fn(Option, T, Option) -> R) -> R { self.root_node.reduce(reducer) } /// Initialises a new Tree struct. /// /// Needs a root value pub fn new(root_val: T) -> Tree { Tree:: { root_node: TreeNode:: { value: root_val, left: None, right: None, }, } } /// Inserts a node to the left of the root node. pub fn insert_left(&mut self, v: T) { self.root_node.insert_left(v); } /// Inserts a node to the right of the root node. pub fn insert_right(&mut self, v: T) { self.root_node.insert_right(v); } } impl Display for Tree { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.root_node) } } /// A node in a binary tree. /// /// Can be used for many interesting algorithmic things. pub struct TreeNode { pub value: T, /// The left node, may be `None`. pub left: Option>>, /// The right node, may be `None`. pub right: Option>>, } impl Display for TreeNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}{}{}", match &self.left { Some(v) => format!("({})<-", v), None => "".to_string(), }, format!("({})", self.value), match &self.right { Some(v) => format!("->({})", v), None => "".to_string(), } ) } } impl TreeNode { /// Initialises a new node for a Tree. pub fn new(v: T) -> TreeNode { TreeNode { value: v, left: None, right: None, } } /// Recursively reduces each element in tree. pub fn reduce(&self, reducer: fn(Option, T, Option) -> R) -> R { let left_val = match &self.left { Some(node) => Some(node.reduce(reducer)), None => None, }; let right_val = match &self.right { Some(node) => Some(node.reduce(reducer)), None => None, }; reducer(left_val, self.value, right_val) } /// Recursively inserts to the left of node until there is one empty space. pub fn insert_left(&mut self, value: T) { if let Some(node) = &mut self.left { node.insert_left(value) } self.left = Some(Box::new(TreeNode { value, left: None, right: None, })); } /// Recursively inserts to the right of node until there is one empty space. pub fn insert_right(&mut self, value: T) { if let Some(node) = &mut self.right { node.insert_right(value) } self.right = Some(Box::new(TreeNode::new(value))) } }