From ff2d0ad4d819c416e54f48fa175f8bc000eec202 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Wed, 19 Feb 2020 18:04:09 -0700 Subject: [PATCH 01/80] broken stuff --- src/main.rs | 7 +- src/red_black_tree.rs | 178 ++++++++++++++++++++++++++++-------------- 2 files changed, 127 insertions(+), 58 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4a2a5d7..18b7ef3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,5 +2,10 @@ mod avl_tree; mod red_black_tree; fn main() { - println!("Hello, world!"); + // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + // rbt.insert_node2(5); + // println!("{}", rbt.size()); + + let mut treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); + println!("{:?}", treenode.va()); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 2e57f7d..b197d5c 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -8,51 +8,115 @@ enum NodeColor { Black, } -// type Tree = Rc>>; -// type RedBlackTree= Option; - -struct TreeNode { - pub color: NodeColor, - pub value: Option, - pub parent: Option>>>, - left: Option>>>, - right: Option>>> +type Tree = Rc>>; +type RedBlackTree = Option>; + +pub struct TreeNode { + color: NodeColor, + value: T, + parent: RedBlackTree, + left: RedBlackTree, + right: RedBlackTree +} + +pub trait TreeNodeTraits { + fn color(&self) -> NodeColor; + fn value(&self) -> T; + fn parent(&self) -> RedBlackTree; + fn left(&self) -> RedBlackTree; + fn right(&self) -> RedBlackTree; + fn set_color(&self, color: NodeColor); + fn set_value(&self, value: T); + fn set_parent(&self, parent: RedBlackTree); + fn set_left(&self, left: RedBlackTree); + fn set_right(&self, right: RedBlackTree); } impl TreeNode { - fn new(val: T) -> TreeNode { + pub fn new(val: T) -> TreeNode { TreeNode { color: NodeColor::Black, - value: Some(val), + value: val, parent: None, left: None, right: None } } - fn is_some(& self) -> bool { - match self.value { - Some(_) => true, - None => false, - } - } + // fn is_some(& self) -> bool { + // match self.value { + // Some(_) => true, + // None => false, + // } + // } - fn new_wrapped(val: T) -> Option>>> { + fn new_wrapped(val: T) -> RedBlackTree { Some(Rc::new(RefCell::new(TreeNode::new(val)))) } - // fn unwrap(node: Option>>>) -> TreeNode { + pub fn va(&self) -> T { + self.value() + } + + // fn unwrap(node: RedBlackTree) -> TreeNode { // node.as_ref().unwrap().as_ref().get_mut() // } } -struct RBTree { - root: Option>>>, +impl TreeNodeTraits for TreeNode { + fn color(&self) -> NodeColor { + self.color.clone() + } + + fn value(&self) -> T { + self.value + } + + fn parent(&self) -> RedBlackTree { + self.parent.clone() + } + + fn left(&self) -> RedBlackTree { + self.left.clone() + } + + fn right(&self) -> RedBlackTree { + self.right.clone() + } + + fn set_color(&self, color: NodeColor) { + self.color = color; + } + + fn set_value(&self, value: T) { + self.value = value; + } + + fn set_parent(&self, parent: RedBlackTree) { + self.parent = parent; + } + + fn set_left(&self, left: RedBlackTree) { + self.left = left; + } + + fn set_right(&self, right: RedBlackTree) { + self.right = right; + } +} + +pub struct RBTree { + root: RedBlackTree, len: usize } -impl RBTree - where T: Ord + PartialEq + PartialOrd { +impl RBTree where T: Ord + PartialEq + PartialOrd { + pub fn new() -> RBTree { + RBTree { + root: None, + len: 0 + } + } // fn rotate() { // } @@ -93,41 +157,41 @@ impl RBTree } pub fn insert_node2(&mut self, value: T) { - if self.len == 0 { - self.root = TreeNode::new_wrapped(value); - } else { - let root_unwrapped = self.root.unwrap().borrow(); - let mut new_node = TreeNode::new(value); - let mut subroot = root_unwrapped; - let is_left_child = true; - - while new_node.value != root_unwrapped.value && new_node.parent.is_none() { - - if !subroot.is_some() { - - // insert at empty node - new_node.parent = subroot.parent; - let mut unwrapped_parent = subroot.parent.unwrap().borrow(); - - if is_left_child { - unwrapped_parent.left = TreeNode::new_wrapped(value); - } else { - unwrapped_parent.right = TreeNode::new_wrapped(value); - } - - } else if value < subroot.value.unwrap() { - subroot = subroot.left.unwrap().borrow(); - is_left_child = true; + // if self.len == 0 { + // self.root = TreeNode::new_wrapped(value); + // } else { + // let root_unwrapped = self.root.unwrap().borrow(); + // let mut new_node = TreeNode::new(value); + // let mut subroot = root_unwrapped; + // let is_left_child = true; + + // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { + + // if !subroot.is_some() { + + // // insert at empty node + // new_node.parent = subroot.parent; + // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); + + // if is_left_child { + // unwrapped_parent.left = TreeNode::new_wrapped(value); + // } else { + // unwrapped_parent.right = TreeNode::new_wrapped(value); + // } + + // } else if value < subroot.value.unwrap() { + // subroot = subroot.left.unwrap().borrow(); + // is_left_child = true; - } else { //value > curr_node_unwrapped.value { - subroot = subroot.right.unwrap().borrow(); - is_left_child = false; - } - } - - // rebalance the tree here i guess and fix colors - fixInsColor(); - } + // } else { //value > curr_node_unwrapped.value { + // subroot = subroot.right.unwrap().borrow(); + // is_left_child = false; + // } + // } + + // // rebalance the tree here i guess and fix colors + // fixInsColor(); + // } } From 554b3315cbef6c2c14e01adf97836dc9ab259105 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Wed, 19 Feb 2020 23:07:15 -0700 Subject: [PATCH 02/80] traits finally work --- src/main.rs | 14 +- src/red_black_tree.rs | 419 +++++++++++++++++++++++------------------- 2 files changed, 238 insertions(+), 195 deletions(-) diff --git a/src/main.rs b/src/main.rs index 18b7ef3..5a419fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,21 @@ mod avl_tree; mod red_black_tree; +use red_black_tree::*; + fn main() { // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); // rbt.insert_node2(5); // println!("{}", rbt.size()); - let mut treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); - println!("{:?}", treenode.va()); + let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); + + println!("{:?}", treenode.value()); + println!("{:?}", treenode.color()); + + treenode.set_color(red_black_tree::NodeColor::Red); + println!("{:?}", treenode.color()); + + treenode.set_value(10); + println!("{:?}", treenode.value()); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index b197d5c..faebbb8 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -3,252 +3,285 @@ use std::rc::Rc; #[derive(Clone, Debug, PartialEq)] -enum NodeColor { +pub enum NodeColor { Red, Black, } -type Tree = Rc>>; -type RedBlackTree = Option>; +pub type TreeNode = Option>>>; -pub struct TreeNode { +pub struct Node { color: NodeColor, - value: T, - parent: RedBlackTree, - left: RedBlackTree, - right: RedBlackTree + value: Option, + parent: TreeNode, + left: TreeNode, + right: TreeNode } -pub trait TreeNodeTraits { +pub trait NodeTraits { + fn new(val: T) -> TreeNode; + fn unwrapped(&self) -> Rc>>; fn color(&self) -> NodeColor; - fn value(&self) -> T; - fn parent(&self) -> RedBlackTree; - fn left(&self) -> RedBlackTree; - fn right(&self) -> RedBlackTree; + fn value(&self) -> Option; + fn parent(&self) -> TreeNode; + fn left(&self) -> TreeNode; + fn right(&self) -> TreeNode; fn set_color(&self, color: NodeColor); fn set_value(&self, value: T); - fn set_parent(&self, parent: RedBlackTree); - fn set_left(&self, left: RedBlackTree); - fn set_right(&self, right: RedBlackTree); + fn set_parent(&self, parent: TreeNode); + fn set_left(&self, left: TreeNode); + fn set_right(&self, right: TreeNode); } -impl TreeNode { - pub fn new(val: T) -> TreeNode { - TreeNode { +// impl Node { +// pub fn new(val: T) -> Node { +// Node { +// color: NodeColor::Black, +// value: val, +// parent: None, +// left: None, +// right: None +// } +// } + +// // fn is_some(& self) -> bool { +// // match self.value { +// // Some(_) => true, +// // None => false, +// // } +// // } + +// fn new_wrapped(val: T) -> TreeNode { +// Some(Rc::new(RefCell::new(Node::new(val)))) +// } + +// pub fn va(&self) -> T { +// self.value() +// } + +// // fn unwrap(node: TreeNode) -> Node { +// // node.as_ref().unwrap().as_ref().get_mut() +// // } +// } + +impl NodeTraits for TreeNode where T: Copy { + fn new(val: T) -> TreeNode { + Some(Rc::new(RefCell::new(Node { color: NodeColor::Black, - value: val, + value: Some(val), parent: None, left: None, right: None - } - } - - // fn is_some(& self) -> bool { - // match self.value { - // Some(_) => true, - // None => false, - // } - // } - - fn new_wrapped(val: T) -> RedBlackTree { - Some(Rc::new(RefCell::new(TreeNode::new(val)))) + }))) } - pub fn va(&self) -> T { - self.value() + fn unwrapped(&self) -> Rc>> { + match self { + Some(tree_node) => Rc::clone(&tree_node), + None => panic!("Error unwrapping tree node") + } } - // fn unwrap(node: RedBlackTree) -> TreeNode { - // node.as_ref().unwrap().as_ref().get_mut() - // } -} - -impl TreeNodeTraits for TreeNode { fn color(&self) -> NodeColor { - self.color.clone() + match self { + Some(tree_node) => tree_node.borrow().color.clone(), + None => panic!("Error getting tree node color") + } } - fn value(&self) -> T { - self.value + fn value(&self) -> Option { + match self { + Some(tree_node) => tree_node.borrow().value, + None => panic!("Error getting tree node value") + } } - fn parent(&self) -> RedBlackTree { - self.parent.clone() + fn parent(&self) -> TreeNode { + match self { + Some(tree_node) => tree_node.borrow().parent.clone(), + None => panic!("Error getting tree node parent") + } } - fn left(&self) -> RedBlackTree { - self.left.clone() + fn left(&self) -> TreeNode { + match self { + Some(tree_node) => tree_node.borrow().left.clone(), + None => panic!("Error getting tree node left child") + } } - fn right(&self) -> RedBlackTree { - self.right.clone() + fn right(&self) -> TreeNode { + match self { + Some(tree_node) => tree_node.borrow().right.clone(), + None => panic!("Error getting tree node right child") + } } fn set_color(&self, color: NodeColor) { - self.color = color; + self.unwrapped().borrow_mut().color = color; } fn set_value(&self, value: T) { - self.value = value; + self.unwrapped().borrow_mut().value = Some(value); } - fn set_parent(&self, parent: RedBlackTree) { - self.parent = parent; + fn set_parent(&self, parent: TreeNode) { + self.unwrapped().borrow_mut().parent = parent; } - fn set_left(&self, left: RedBlackTree) { - self.left = left; + fn set_left(&self, left: TreeNode) { + self.unwrapped().borrow_mut().left = left; } - fn set_right(&self, right: RedBlackTree) { - self.right = right; + fn set_right(&self, right: TreeNode) { + self.unwrapped().borrow_mut().right = right; } } -pub struct RBTree { - root: RedBlackTree, - len: usize -} - -impl RBTree where T: Ord + PartialEq + PartialOrd { - pub fn new() -> RBTree { - RBTree { - root: None, - len: 0 - } - } - // fn rotate() { - - // } +// pub struct RBTree { +// root: TreeNode, +// len: usize +// } + +// impl RBTree where T: Ord + PartialEq + PartialOrd { +// pub fn new() -> RBTree { +// RBTree { +// root: None, +// len: 0 +// } +// } +// // fn rotate() { + +// // } - // fn fixDelColor() { +// // fn fixDelColor() { - // } +// // } - fn fixInsColor() { +// fn fixInsColor() { - } +// } - pub fn delete_node(&mut self) { - self.len -= 1; - } +// pub fn delete_node(&mut self) { +// self.len -= 1; +// } - pub fn height(&self) -> usize { - // TODO: add match statements for left and right heights - // need to borrow and match stuff. see commented code below - - // let left_height = self.root.left; - // let right_height = self.root.right; - - // let left_height = match *self.left.borrow() { - // Some(ref left) => left.height(), - // None => 0, - // }; - // let right_height = match *self.right.borrow() { - // Some(ref right) => right.height(), - // None => 0, - // }; - // if left_height > right_height { - // left_height += 1; - // } else { - // right_height += 1; - // } - 0 - } - - pub fn insert_node2(&mut self, value: T) { - // if self.len == 0 { - // self.root = TreeNode::new_wrapped(value); - // } else { - // let root_unwrapped = self.root.unwrap().borrow(); - // let mut new_node = TreeNode::new(value); - // let mut subroot = root_unwrapped; - // let is_left_child = true; - - // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { - - // if !subroot.is_some() { - - // // insert at empty node - // new_node.parent = subroot.parent; - // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); - - // if is_left_child { - // unwrapped_parent.left = TreeNode::new_wrapped(value); - // } else { - // unwrapped_parent.right = TreeNode::new_wrapped(value); - // } - - // } else if value < subroot.value.unwrap() { - // subroot = subroot.left.unwrap().borrow(); - // is_left_child = true; +// pub fn height(&self) -> usize { +// // TODO: add match statements for left and right heights +// // need to borrow and match stuff. see commented code below + +// // let left_height = self.root.left; +// // let right_height = self.root.right; + +// // let left_height = match *self.left.borrow() { +// // Some(ref left) => left.height(), +// // None => 0, +// // }; +// // let right_height = match *self.right.borrow() { +// // Some(ref right) => right.height(), +// // None => 0, +// // }; +// // if left_height > right_height { +// // left_height += 1; +// // } else { +// // right_height += 1; +// // } +// 0 +// } + +// pub fn insert_node2(&mut self, value: T) { +// // if self.len == 0 { +// // self.root = Node::new_wrapped(value); +// // } else { +// // let root_unwrapped = self.root.unwrap().borrow(); +// // let mut new_node = Node::new(value); +// // let mut subroot = root_unwrapped; +// // let is_left_child = true; + +// // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { + +// // if !subroot.is_some() { + +// // // insert at empty node +// // new_node.parent = subroot.parent; +// // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); + +// // if is_left_child { +// // unwrapped_parent.left = Node::new_wrapped(value); +// // } else { +// // unwrapped_parent.right = Node::new_wrapped(value); +// // } + +// // } else if value < subroot.value.unwrap() { +// // subroot = subroot.left.unwrap().borrow(); +// // is_left_child = true; - // } else { //value > curr_node_unwrapped.value { - // subroot = subroot.right.unwrap().borrow(); - // is_left_child = false; - // } - // } - - // // rebalance the tree here i guess and fix colors - // fixInsColor(); - // } - } - - - // pub fn insert_node(&mut self, value: T) { - // if self.len == 0 { - // self.root = TreeNode::new_wrapped(value); - // } else { - // let curr_node = &self.root; - // let curr_node_unwrapped = curr_node.as_ref().unwrap().as_ref().get_mut(); - - // if value == curr_node_unwrapped.value { - // return - // } - - - - // // loop {} - // let curr_node = if value < curr_node_unwrapped.value { - // curr_node_unwrapped.left - // } else { - // curr_node_unwrapped.right - // }; - - // let new_node = TreeNode::new(value); - // new_node.parent = curr_node_unwrapped.parent; - - // match curr_node { - // // _ => Some(Rc::new(RefCell::new(new_node))), - // Some(sub_node) => self.insert_node(value), - // None => { - // // let temp = Some(Rc::new(RefCell::new(TreeNode::new(value)))); - // // *curr_node = temp; - // *curr_node = Some(Rc::new(RefCell::new(new_node))); - // }, - // // &mut Some(ref mut sub_node) => sub_node.insert_node(value), - // // &mut None => { - // // let temp = TreeNode { value: value, left_child: None, right_child: None}; - // // let boxed_node = Some(Box::new(temp)); - // // *new_node = boxed_node; - // // } - // } - - // // balance the tree here i guess. need to pass in node tho - // fixInsColor(); - // } - // self.len += 1; - // } +// // } else { //value > curr_node_unwrapped.value { +// // subroot = subroot.right.unwrap().borrow(); +// // is_left_child = false; +// // } +// // } + +// // // rebalance the tree here i guess and fix colors +// // fixInsColor(); +// // } +// } + + +// // pub fn insert_node(&mut self, value: T) { +// // if self.len == 0 { +// // self.root = Node::new_wrapped(value); +// // } else { +// // let curr_node = &self.root; +// // let curr_node_unwrapped = curr_node.as_ref().unwrap().as_ref().get_mut(); + +// // if value == curr_node_unwrapped.value { +// // return +// // } + + + +// // // loop {} +// // let curr_node = if value < curr_node_unwrapped.value { +// // curr_node_unwrapped.left +// // } else { +// // curr_node_unwrapped.right +// // }; + +// // let new_node = Node::new(value); +// // new_node.parent = curr_node_unwrapped.parent; + +// // match curr_node { +// // // _ => Some(Rc::new(RefCell::new(new_node))), +// // Some(sub_node) => self.insert_node(value), +// // None => { +// // // let temp = Some(Rc::new(RefCell::new(Node::new(value)))); +// // // *curr_node = temp; +// // *curr_node = Some(Rc::new(RefCell::new(new_node))); +// // }, +// // // &mut Some(ref mut sub_node) => sub_node.insert_node(value), +// // // &mut None => { +// // // let temp = Node { value: value, left_child: None, right_child: None}; +// // // let boxed_node = Some(Box::new(temp)); +// // // *new_node = boxed_node; +// // // } +// // } + +// // // balance the tree here i guess. need to pass in node tho +// // fixInsColor(); +// // } +// // self.len += 1; +// // } - pub fn is_empty(&self) -> bool { - self.len == 0 - } +// pub fn is_empty(&self) -> bool { +// self.len == 0 +// } - pub fn print() { +// pub fn print() { - } +// } - pub fn size(&self) -> usize { - self.len - } -} \ No newline at end of file +// pub fn size(&self) -> usize { +// self.len +// } +// } \ No newline at end of file From d7c85280048282a8e1aed0bcba4a1dbe4a1ac389 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Wed, 19 Feb 2020 23:37:21 -0700 Subject: [PATCH 03/80] cleanup --- src/main.rs | 11 +- src/red_black_tree.rs | 357 +++++++++++++++++++++--------------------- 2 files changed, 187 insertions(+), 181 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5a419fd..c991399 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,7 @@ mod red_black_tree; use red_black_tree::*; fn main() { - // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - // rbt.insert_node2(5); - // println!("{}", rbt.size()); - + // Test TreeNode let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); println!("{:?}", treenode.value()); @@ -18,4 +15,10 @@ fn main() { treenode.set_value(10); println!("{:?}", treenode.value()); + + + // Test RBTree + let rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + // rbt.insert_node2(5); + // println!("{}", rbt.size()); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index faebbb8..d9ecc8d 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -3,6 +3,8 @@ use std::rc::Rc; #[derive(Clone, Debug, PartialEq)] +/********** TreeNode Helpers **********/ + pub enum NodeColor { Red, Black, @@ -33,37 +35,6 @@ pub trait NodeTraits { fn set_right(&self, right: TreeNode); } -// impl Node { -// pub fn new(val: T) -> Node { -// Node { -// color: NodeColor::Black, -// value: val, -// parent: None, -// left: None, -// right: None -// } -// } - -// // fn is_some(& self) -> bool { -// // match self.value { -// // Some(_) => true, -// // None => false, -// // } -// // } - -// fn new_wrapped(val: T) -> TreeNode { -// Some(Rc::new(RefCell::new(Node::new(val)))) -// } - -// pub fn va(&self) -> T { -// self.value() -// } - -// // fn unwrap(node: TreeNode) -> Node { -// // node.as_ref().unwrap().as_ref().get_mut() -// // } -// } - impl NodeTraits for TreeNode where T: Copy { fn new(val: T) -> TreeNode { Some(Rc::new(RefCell::new(Node { @@ -138,150 +109,182 @@ impl NodeTraits for TreeNode where T: Copy { } } -// pub struct RBTree { -// root: TreeNode, -// len: usize -// } - -// impl RBTree where T: Ord + PartialEq + PartialOrd { -// pub fn new() -> RBTree { -// RBTree { -// root: None, -// len: 0 -// } -// } -// // fn rotate() { - -// // } - -// // fn fixDelColor() { - -// // } - -// fn fixInsColor() { - -// } - -// pub fn delete_node(&mut self) { -// self.len -= 1; -// } - -// pub fn height(&self) -> usize { -// // TODO: add match statements for left and right heights -// // need to borrow and match stuff. see commented code below - -// // let left_height = self.root.left; -// // let right_height = self.root.right; - -// // let left_height = match *self.left.borrow() { -// // Some(ref left) => left.height(), -// // None => 0, -// // }; -// // let right_height = match *self.right.borrow() { -// // Some(ref right) => right.height(), -// // None => 0, -// // }; -// // if left_height > right_height { -// // left_height += 1; -// // } else { -// // right_height += 1; -// // } -// 0 -// } - -// pub fn insert_node2(&mut self, value: T) { -// // if self.len == 0 { -// // self.root = Node::new_wrapped(value); -// // } else { -// // let root_unwrapped = self.root.unwrap().borrow(); -// // let mut new_node = Node::new(value); -// // let mut subroot = root_unwrapped; -// // let is_left_child = true; - -// // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { - -// // if !subroot.is_some() { - -// // // insert at empty node -// // new_node.parent = subroot.parent; -// // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); - -// // if is_left_child { -// // unwrapped_parent.left = Node::new_wrapped(value); -// // } else { -// // unwrapped_parent.right = Node::new_wrapped(value); -// // } - -// // } else if value < subroot.value.unwrap() { -// // subroot = subroot.left.unwrap().borrow(); -// // is_left_child = true; +/********** RBTree Helpers **********/ +pub struct RBTree { + root: TreeNode, + len: usize +} + +pub trait RBTreeTraits { + fn new() -> RBTree; + fn height(&self) -> usize; + fn is_empty(&self) -> bool; + fn size(&self) -> usize; + fn rotate_left(&self, node: TreeNode); + fn rotate_right(&self, node: TreeNode); + fn fix_ins_color(&self, node: TreeNode); + fn fix_del_color(&self, node: TreeNode); + fn insert_node(&self, value: T); + fn delete_node(&self, value: T); + fn print(&self); +} + +impl RBTreeTraits for RBTree { + fn new() -> RBTree { + RBTree { + root: None, + len: 0 + } + } + + // TODO + fn height(&self) -> usize { + // // TODO: add match statements for left and right heights + // // need to borrow and match stuff. see commented code below + + // let left_height = self.root.left; + // let right_height = self.root.right; + + // let left_height = match *self.left.borrow() { + // Some(ref left) => left.height(), + // None => 0, + // }; + // let right_height = match *self.right.borrow() { + // Some(ref right) => right.height(), + // None => 0, + // }; + // if left_height > right_height { + // left_height += 1; + // } else { + // right_height += 1; + // } + 0 + } + + fn is_empty(&self) -> bool { + self.root.is_none() + } + + fn size(&self) -> usize { + self.len + } + + // TODO + fn rotate_left(&self, node: TreeNode) { + + } + + // TODO + fn rotate_right(&self, node: TreeNode) { + + } + + // TODO + fn fix_ins_color(&self, node: TreeNode) { + + } + + // TODO + fn insert_node(&self, value: T) { + + } + + // TODO + fn fix_del_color(&self, node: TreeNode) { + + } + + // TODO + fn delete_node(&self, value: T) { + + } + + // TODO + fn print(&self) { + + } +} + + // pub fn insert_node2(&mut self, value: T) { + // // if self.len == 0 { + // // self.root = Node::new_wrapped(value); + // // } else { + // // let root_unwrapped = self.root.unwrap().borrow(); + // // let mut new_node = Node::new(value); + // // let mut subroot = root_unwrapped; + // // let is_left_child = true; + + // // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { + + // // if !subroot.is_some() { + + // // // insert at empty node + // // new_node.parent = subroot.parent; + // // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); + + // // if is_left_child { + // // unwrapped_parent.left = Node::new_wrapped(value); + // // } else { + // // unwrapped_parent.right = Node::new_wrapped(value); + // // } + + // // } else if value < subroot.value.unwrap() { + // // subroot = subroot.left.unwrap().borrow(); + // // is_left_child = true; -// // } else { //value > curr_node_unwrapped.value { -// // subroot = subroot.right.unwrap().borrow(); -// // is_left_child = false; -// // } -// // } - -// // // rebalance the tree here i guess and fix colors -// // fixInsColor(); -// // } -// } - - -// // pub fn insert_node(&mut self, value: T) { -// // if self.len == 0 { -// // self.root = Node::new_wrapped(value); -// // } else { -// // let curr_node = &self.root; -// // let curr_node_unwrapped = curr_node.as_ref().unwrap().as_ref().get_mut(); - -// // if value == curr_node_unwrapped.value { -// // return -// // } - - - -// // // loop {} -// // let curr_node = if value < curr_node_unwrapped.value { -// // curr_node_unwrapped.left -// // } else { -// // curr_node_unwrapped.right -// // }; - -// // let new_node = Node::new(value); -// // new_node.parent = curr_node_unwrapped.parent; - -// // match curr_node { -// // // _ => Some(Rc::new(RefCell::new(new_node))), -// // Some(sub_node) => self.insert_node(value), -// // None => { -// // // let temp = Some(Rc::new(RefCell::new(Node::new(value)))); -// // // *curr_node = temp; -// // *curr_node = Some(Rc::new(RefCell::new(new_node))); -// // }, -// // // &mut Some(ref mut sub_node) => sub_node.insert_node(value), -// // // &mut None => { -// // // let temp = Node { value: value, left_child: None, right_child: None}; -// // // let boxed_node = Some(Box::new(temp)); -// // // *new_node = boxed_node; -// // // } -// // } - -// // // balance the tree here i guess. need to pass in node tho -// // fixInsColor(); -// // } -// // self.len += 1; -// // } - -// pub fn is_empty(&self) -> bool { -// self.len == 0 -// } - -// pub fn print() { - -// } - -// pub fn size(&self) -> usize { -// self.len -// } -// } \ No newline at end of file + // // } else { //value > curr_node_unwrapped.value { + // // subroot = subroot.right.unwrap().borrow(); + // // is_left_child = false; + // // } + // // } + + // // // rebalance the tree here i guess and fix colors + // // fixInsColor(); + // // } + // } + + + // // pub fn insert_node(&mut self, value: T) { + // // if self.len == 0 { + // // self.root = Node::new_wrapped(value); + // // } else { + // // let curr_node = &self.root; + // // let curr_node_unwrapped = curr_node.as_ref().unwrap().as_ref().get_mut(); + + // // if value == curr_node_unwrapped.value { + // // return + // // } + + + + // // // loop {} + // // let curr_node = if value < curr_node_unwrapped.value { + // // curr_node_unwrapped.left + // // } else { + // // curr_node_unwrapped.right + // // }; + + // // let new_node = Node::new(value); + // // new_node.parent = curr_node_unwrapped.parent; + + // // match curr_node { + // // // _ => Some(Rc::new(RefCell::new(new_node))), + // // Some(sub_node) => self.insert_node(value), + // // None => { + // // // let temp = Some(Rc::new(RefCell::new(Node::new(value)))); + // // // *curr_node = temp; + // // *curr_node = Some(Rc::new(RefCell::new(new_node))); + // // }, + // // // &mut Some(ref mut sub_node) => sub_node.insert_node(value), + // // // &mut None => { + // // // let temp = Node { value: value, left_child: None, right_child: None}; + // // // let boxed_node = Some(Box::new(temp)); + // // // *new_node = boxed_node; + // // // } + // // } + + // // // balance the tree here i guess. need to pass in node tho + // // fixInsColor(); + // // } + // // self.len += 1; + // // } \ No newline at end of file From f14a2d038dd01aa0e5db127f0c7c3421a7b0c3f3 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 01:51:17 -0700 Subject: [PATCH 04/80] progress --- src/main.rs | 11 ++- src/red_black_tree.rs | 152 +++++++++++++++--------------------------- 2 files changed, 60 insertions(+), 103 deletions(-) diff --git a/src/main.rs b/src/main.rs index c991399..c7b295b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,12 @@ fn main() { // Test RBTree - let rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - // rbt.insert_node2(5); - // println!("{}", rbt.size()); + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + rbt.insert_node(5); + println!("{}", rbt.size()); + // won't know for sure if the following will work unless fix_insert_color is done + rbt.insert_node(70); + println!("{}", rbt.size()); + rbt.insert_node(35); + println!("{}", rbt.size()); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index d9ecc8d..c152fe7 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -3,7 +3,7 @@ use std::rc::Rc; #[derive(Clone, Debug, PartialEq)] -/********** TreeNode Helpers **********/ +/******************** TreeNode Helpers ********************/ pub enum NodeColor { Red, @@ -26,7 +26,7 @@ pub trait NodeTraits { fn color(&self) -> NodeColor; fn value(&self) -> Option; fn parent(&self) -> TreeNode; - fn left(&self) -> TreeNode; + fn left(&self) -> TreeNode; fn right(&self) -> TreeNode; fn set_color(&self, color: NodeColor); fn set_value(&self, value: T); @@ -63,7 +63,7 @@ impl NodeTraits for TreeNode where T: Copy { fn value(&self) -> Option { match self { Some(tree_node) => tree_node.borrow().value, - None => panic!("Error getting tree node value") + None => None } } @@ -109,7 +109,8 @@ impl NodeTraits for TreeNode where T: Copy { } } -/********** RBTree Helpers **********/ +/******************** RBTree Helpers ********************/ + pub struct RBTree { root: TreeNode, len: usize @@ -120,16 +121,17 @@ pub trait RBTreeTraits { fn height(&self) -> usize; fn is_empty(&self) -> bool; fn size(&self) -> usize; + fn contains(&self, value: T) -> bool; fn rotate_left(&self, node: TreeNode); fn rotate_right(&self, node: TreeNode); - fn fix_ins_color(&self, node: TreeNode); - fn fix_del_color(&self, node: TreeNode); - fn insert_node(&self, value: T); + fn fix_insert_color(&self, node: TreeNode); + fn fix_delete_color(&self, node: TreeNode); + fn insert_node(&mut self, value: T); fn delete_node(&self, value: T); fn print(&self); } -impl RBTreeTraits for RBTree { +impl RBTreeTraits for RBTree where T: Copy + PartialOrd { fn new() -> RBTree { RBTree { root: None, @@ -169,28 +171,62 @@ impl RBTreeTraits for RBTree { self.len } - // TODO - fn rotate_left(&self, node: TreeNode) { - + // TODO (extra thing i guess) + fn contains(&self, value: T) -> bool { + false } // TODO - fn rotate_right(&self, node: TreeNode) { + fn rotate_left(&self, node: TreeNode) { } // TODO - fn fix_ins_color(&self, node: TreeNode) { + fn rotate_right(&self, node: TreeNode) { } // TODO - fn insert_node(&self, value: T) { + fn fix_insert_color(&self, node: TreeNode) { + + } + + fn insert_node(&mut self, value: T) { + let new_node = TreeNode::new(value); + + if self.root.is_none() { + self.root = TreeNode::new(value); + } else if self.contains(value) { + println!("Value already exists!"); + return; + } else { + let mut curr_node = self.root.clone(); + let mut is_left_child = true; + + while curr_node.value().is_some() { + if value < curr_node.value().unwrap() { + curr_node = curr_node.left(); + is_left_child = true; + } else { + curr_node = curr_node.right(); + is_left_child = false; + } + } + + new_node.set_parent(curr_node.parent()); + if is_left_child { + curr_node.parent().set_left(new_node.clone()); + } else { + curr_node.parent().set_right(new_node.clone()); + } + } + self.fix_insert_color(new_node.clone()); + self.len += 1; } // TODO - fn fix_del_color(&self, node: TreeNode) { + fn fix_delete_color(&self, node: TreeNode) { } @@ -203,88 +239,4 @@ impl RBTreeTraits for RBTree { fn print(&self) { } -} - - // pub fn insert_node2(&mut self, value: T) { - // // if self.len == 0 { - // // self.root = Node::new_wrapped(value); - // // } else { - // // let root_unwrapped = self.root.unwrap().borrow(); - // // let mut new_node = Node::new(value); - // // let mut subroot = root_unwrapped; - // // let is_left_child = true; - - // // while new_node.value != root_unwrapped.value && new_node.parent.is_none() { - - // // if !subroot.is_some() { - - // // // insert at empty node - // // new_node.parent = subroot.parent; - // // let mut unwrapped_parent = subroot.parent.unwrap().borrow(); - - // // if is_left_child { - // // unwrapped_parent.left = Node::new_wrapped(value); - // // } else { - // // unwrapped_parent.right = Node::new_wrapped(value); - // // } - - // // } else if value < subroot.value.unwrap() { - // // subroot = subroot.left.unwrap().borrow(); - // // is_left_child = true; - - // // } else { //value > curr_node_unwrapped.value { - // // subroot = subroot.right.unwrap().borrow(); - // // is_left_child = false; - // // } - // // } - - // // // rebalance the tree here i guess and fix colors - // // fixInsColor(); - // // } - // } - - - // // pub fn insert_node(&mut self, value: T) { - // // if self.len == 0 { - // // self.root = Node::new_wrapped(value); - // // } else { - // // let curr_node = &self.root; - // // let curr_node_unwrapped = curr_node.as_ref().unwrap().as_ref().get_mut(); - - // // if value == curr_node_unwrapped.value { - // // return - // // } - - - - // // // loop {} - // // let curr_node = if value < curr_node_unwrapped.value { - // // curr_node_unwrapped.left - // // } else { - // // curr_node_unwrapped.right - // // }; - - // // let new_node = Node::new(value); - // // new_node.parent = curr_node_unwrapped.parent; - - // // match curr_node { - // // // _ => Some(Rc::new(RefCell::new(new_node))), - // // Some(sub_node) => self.insert_node(value), - // // None => { - // // // let temp = Some(Rc::new(RefCell::new(Node::new(value)))); - // // // *curr_node = temp; - // // *curr_node = Some(Rc::new(RefCell::new(new_node))); - // // }, - // // // &mut Some(ref mut sub_node) => sub_node.insert_node(value), - // // // &mut None => { - // // // let temp = Node { value: value, left_child: None, right_child: None}; - // // // let boxed_node = Some(Box::new(temp)); - // // // *new_node = boxed_node; - // // // } - // // } - - // // // balance the tree here i guess. need to pass in node tho - // // fixInsColor(); - // // } - // // self.len += 1; - // // } \ No newline at end of file +} \ No newline at end of file From c30312e1cfde09e02443c0274be652d36ab12f3c Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 02:53:54 -0700 Subject: [PATCH 05/80] fix_insert_color alsmot done it's 3am yay --- src/red_black_tree.rs | 56 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index c152fe7..a045ed2 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -23,11 +23,14 @@ pub struct Node { pub trait NodeTraits { fn new(val: T) -> TreeNode; fn unwrapped(&self) -> Rc>>; + fn compare(&self, node: &TreeNode) -> bool; fn color(&self) -> NodeColor; fn value(&self) -> Option; fn parent(&self) -> TreeNode; fn left(&self) -> TreeNode; fn right(&self) -> TreeNode; + fn grandparent(&self) -> TreeNode; + fn uncle(&self) -> TreeNode; fn set_color(&self, color: NodeColor); fn set_value(&self, value: T); fn set_parent(&self, parent: TreeNode); @@ -38,7 +41,7 @@ pub trait NodeTraits { impl NodeTraits for TreeNode where T: Copy { fn new(val: T) -> TreeNode { Some(Rc::new(RefCell::new(Node { - color: NodeColor::Black, + color: NodeColor::Red, value: Some(val), parent: None, left: None, @@ -53,6 +56,10 @@ impl NodeTraits for TreeNode where T: Copy { } } + fn compare(&self, node: &TreeNode) -> bool { + Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) + } + fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -70,21 +77,33 @@ impl NodeTraits for TreeNode where T: Copy { fn parent(&self) -> TreeNode { match self { Some(tree_node) => tree_node.borrow().parent.clone(), - None => panic!("Error getting tree node parent") + None => None } } fn left(&self) -> TreeNode { match self { Some(tree_node) => tree_node.borrow().left.clone(), - None => panic!("Error getting tree node left child") + None => None } } fn right(&self) -> TreeNode { match self { Some(tree_node) => tree_node.borrow().right.clone(), - None => panic!("Error getting tree node right child") + None => None + } + } + + fn grandparent(&self) -> TreeNode { + self.parent().parent() + } + + fn uncle(&self) -> TreeNode { + if self.parent().compare(&self.grandparent().left()) { + self.grandparent().right() + } else { + self.grandparent().left() } } @@ -124,7 +143,7 @@ pub trait RBTreeTraits { fn contains(&self, value: T) -> bool; fn rotate_left(&self, node: TreeNode); fn rotate_right(&self, node: TreeNode); - fn fix_insert_color(&self, node: TreeNode); + fn fix_insert_color(&self, node: &TreeNode); fn fix_delete_color(&self, node: TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&self, value: T); @@ -187,8 +206,25 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } // TODO - fn fix_insert_color(&self, node: TreeNode) { - + fn fix_insert_color(&self, node: &TreeNode) { + // case 1 + if node.compare(&self.root) { + node.set_color(NodeColor::Black); + // case 2 + } else if node.parent().color() == NodeColor::Black { + return; + // case 3 + } else if node.parent().color() == NodeColor::Red && node.uncle().color() == NodeColor::Red { + node.parent().set_color(NodeColor::Black); + node.uncle().set_color(NodeColor::Black); + node.grandparent().set_color(NodeColor::Red); + self.fix_insert_color(&node.grandparent()); + // case 4 + } else if node.parent().color() == NodeColor::Red && node.uncle().color() == NodeColor::Black { + // do some more stuff + } else { + // error handling here yay + } } fn insert_node(&mut self, value: T) { @@ -202,7 +238,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } else { let mut curr_node = self.root.clone(); let mut is_left_child = true; - + + // find empty node while curr_node.value().is_some() { if value < curr_node.value().unwrap() { curr_node = curr_node.left(); @@ -213,6 +250,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } } + // place new_node in found spot new_node.set_parent(curr_node.parent()); if is_left_child { curr_node.parent().set_left(new_node.clone()); @@ -221,7 +259,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } } - self.fix_insert_color(new_node.clone()); + self.fix_insert_color(&new_node); self.len += 1; } From cd3579d107508dc089683144745be8a848caee1f Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 03:11:17 -0700 Subject: [PATCH 06/80] fix tiny bug before sleep --- src/red_black_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index a045ed2..e3fc2ce 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -231,7 +231,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { let new_node = TreeNode::new(value); if self.root.is_none() { - self.root = TreeNode::new(value); + self.root = new_node.clone(); } else if self.contains(value) { println!("Value already exists!"); return; From 7251f438e1fc2d66d8f1f5b801689876b63e271c Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 09:11:26 -0700 Subject: [PATCH 07/80] INSERT WORKSSSSSSSSSSSSSSSSSS --- src/main.rs | 2 +- src/red_black_tree.rs | 71 ++++++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index c7b295b..62a9ac9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ fn main() { println!("{:?}", treenode.value()); println!("{:?}", treenode.color()); - treenode.set_color(red_black_tree::NodeColor::Red); + treenode.set_color(red_black_tree::NodeColor::Black); println!("{:?}", treenode.color()); treenode.set_value(10); diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index e3fc2ce..f34b00f 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -33,20 +33,24 @@ pub trait NodeTraits { fn uncle(&self) -> TreeNode; fn set_color(&self, color: NodeColor); fn set_value(&self, value: T); - fn set_parent(&self, parent: TreeNode); - fn set_left(&self, left: TreeNode); - fn set_right(&self, right: TreeNode); + fn set_parent(&mut self, parent: TreeNode); + fn set_left(&mut self, left: TreeNode); + fn set_right(&mut self, right: TreeNode); } impl NodeTraits for TreeNode where T: Copy { fn new(val: T) -> TreeNode { - Some(Rc::new(RefCell::new(Node { + let tree_node = Some(Rc::new(RefCell::new(Node { color: NodeColor::Red, value: Some(val), parent: None, left: None, right: None - }))) + }))); + tree_node.left().set_parent(tree_node.clone()); + tree_node.right().set_parent(tree_node.clone()); + + tree_node } fn unwrapped(&self) -> Rc>> { @@ -63,7 +67,7 @@ impl NodeTraits for TreeNode where T: Copy { fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), - None => panic!("Error getting tree node color") + None => NodeColor::Red } } @@ -115,16 +119,43 @@ impl NodeTraits for TreeNode where T: Copy { self.unwrapped().borrow_mut().value = Some(value); } - fn set_parent(&self, parent: TreeNode) { - self.unwrapped().borrow_mut().parent = parent; + fn set_parent(&mut self, parent: TreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().parent = parent, + None => *self = Some(Rc::new(RefCell::new(Node { + color: self.color(), + value: self.value(), + parent: parent, + left: self.left(), + right: self.right() + }))) + } } - fn set_left(&self, left: TreeNode) { - self.unwrapped().borrow_mut().left = left; + fn set_left(&mut self, left: TreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().left = left, + None => *self = Some(Rc::new(RefCell::new(Node { + color: self.color(), + value: self.value(), + parent: self.parent(), + left: left, + right: self.right() + }))) + } } - fn set_right(&self, right: TreeNode) { - self.unwrapped().borrow_mut().right = right; + fn set_right(&mut self, right: TreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().right = right, + None => *self = Some(Rc::new(RefCell::new(Node { + color: self.color(), + value: self.value(), + parent: self.parent(), + left: self.left(), + right: right + }))) + } } } @@ -228,7 +259,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } fn insert_node(&mut self, value: T) { - let new_node = TreeNode::new(value); + let mut new_node = TreeNode::new(value); if self.root.is_none() { self.root = new_node.clone(); @@ -237,10 +268,12 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { return; } else { let mut curr_node = self.root.clone(); + let mut curr_node_parent: TreeNode = None; let mut is_left_child = true; // find empty node while curr_node.value().is_some() { + curr_node_parent = curr_node.clone(); if value < curr_node.value().unwrap() { curr_node = curr_node.left(); is_left_child = true; @@ -251,11 +284,15 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } // place new_node in found spot - new_node.set_parent(curr_node.parent()); - if is_left_child { - curr_node.parent().set_left(new_node.clone()); + if curr_node_parent.is_some() { + new_node.set_parent(curr_node_parent); + if is_left_child { + curr_node.parent().set_left(new_node.clone()); + } else { + curr_node.parent().set_right(new_node.clone()); + } } else { - curr_node.parent().set_right(new_node.clone()); + panic!("Current node has no parent!"); } } From 381ed65e1a889425dca36cae005be8c7b824eb7f Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 10:39:43 -0700 Subject: [PATCH 08/80] print done --- src/main.rs | 6 +++++- src/red_black_tree.rs | 25 +++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 62a9ac9..b308170 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,9 +21,13 @@ fn main() { let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); rbt.insert_node(5); println!("{}", rbt.size()); - // won't know for sure if the following will work unless fix_insert_color is done + rbt.print(); + rbt.insert_node(70); println!("{}", rbt.size()); + rbt.print(); + rbt.insert_node(35); println!("{}", rbt.size()); + rbt.print(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index f34b00f..ee2bbf7 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -178,10 +178,11 @@ pub trait RBTreeTraits { fn fix_delete_color(&self, node: TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&self, value: T); + fn in_order_traversal(&self, node: &TreeNode); fn print(&self); } -impl RBTreeTraits for RBTree where T: Copy + PartialOrd { +impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { fn new() -> RBTree { RBTree { root: None, @@ -287,16 +288,16 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { if curr_node_parent.is_some() { new_node.set_parent(curr_node_parent); if is_left_child { - curr_node.parent().set_left(new_node.clone()); + new_node.parent().set_left(new_node.clone()); } else { - curr_node.parent().set_right(new_node.clone()); + new_node.parent().set_right(new_node.clone()); } } else { panic!("Current node has no parent!"); } } - self.fix_insert_color(&new_node); + // self.fix_insert_color(&new_node); self.len += 1; } @@ -310,8 +311,20 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd { } - // TODO - fn print(&self) { + fn in_order_traversal(&self, node: &TreeNode) { + if node.is_some() && node.value().is_some() { + self.in_order_traversal(&node.left()); + if node.color() == NodeColor::Red { + print!("<{:?}>", node.value().unwrap()); + } else { + print!("[{:?}]", node.value().unwrap()); + } + self.in_order_traversal(&node.right()); + } + } + fn print(&self) { + self.in_order_traversal(&self.root); + println!(); } } \ No newline at end of file From 6aa5e7e35e8b9b636d5dfe72b7cc02104694c7c6 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 10:49:54 -0700 Subject: [PATCH 09/80] small change + some testing --- src/main.rs | 12 ++++++++++++ src/red_black_tree.rs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index b308170..2abdffa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,4 +30,16 @@ fn main() { rbt.insert_node(35); println!("{}", rbt.size()); rbt.print(); + + rbt.insert_node(8); + println!("{}", rbt.size()); + rbt.print(); + + rbt.insert_node(100); + println!("{}", rbt.size()); + rbt.print(); + + rbt.insert_node(60); + println!("{}", rbt.size()); + rbt.print(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index ee2bbf7..eaee9f5 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -262,7 +262,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb fn insert_node(&mut self, value: T) { let mut new_node = TreeNode::new(value); - if self.root.is_none() { + if self.is_empty() { self.root = new_node.clone(); } else if self.contains(value) { println!("Value already exists!"); From 22a5d3de0a09f1970d6fb8b6c521f701cb10b921 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 20 Feb 2020 20:46:32 -0700 Subject: [PATCH 10/80] kinda done height --- src/main.rs | 23 ++++++++++++----- src/red_black_tree.rs | 58 ++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2abdffa..936ff4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,28 +18,39 @@ fn main() { // Test RBTree + println!("\n==== Start Testing RBTree Here ====\n"); let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + println!("empty height = {}", rbt.height()); + rbt.insert_node(5); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height with 1 node = {}", rbt.height()); + // HEIGHTS ARE OFF BY ONE AND IDK WHY YET rbt.insert_node(70); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height = {}", rbt.height()); rbt.insert_node(35); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height = {}", rbt.height()); rbt.insert_node(8); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height = {}", rbt.height()); rbt.insert_node(100); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height = {}", rbt.height()); rbt.insert_node(60); - println!("{}", rbt.size()); + println!("size = {}", rbt.size()); rbt.print(); + println!("height = {}", rbt.height()); + } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index eaee9f5..c448d01 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::f32; #[derive(Clone, Debug, PartialEq)] @@ -36,6 +37,7 @@ pub trait NodeTraits { fn set_parent(&mut self, parent: TreeNode); fn set_left(&mut self, left: TreeNode); fn set_right(&mut self, right: TreeNode); + fn node_height(&self) -> usize; } impl NodeTraits for TreeNode where T: Copy { @@ -157,6 +159,25 @@ impl NodeTraits for TreeNode where T: Copy { }))) } } + + fn node_height(&self) -> usize { + + let left_height = match &*self { + Some(_) => self.left().node_height(), + None => 0, + }; + let right_height = match &*self { + Some(_) => self.right().node_height(), + None => 0, + }; + + if left_height > right_height { + left_height + 1 + } else { + right_height + 1 + } + + } } /******************** RBTree Helpers ********************/ @@ -192,26 +213,14 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn height(&self) -> usize { - // // TODO: add match statements for left and right heights - // // need to borrow and match stuff. see commented code below - - // let left_height = self.root.left; - // let right_height = self.root.right; - - // let left_height = match *self.left.borrow() { - // Some(ref left) => left.height(), - // None => 0, - // }; - // let right_height = match *self.right.borrow() { - // Some(ref right) => right.height(), - // None => 0, - // }; - // if left_height > right_height { - // left_height += 1; - // } else { - // right_height += 1; - // } - 0 + + if self.len > 1 { + let length = self.len as f32; + length.log2() as usize + // self.root.node_height() + } else { + 0 + } } fn is_empty(&self) -> bool { @@ -229,6 +238,9 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn rotate_left(&self, node: TreeNode) { + let parent = node.parent(); + let grandparent = node.grandparent(); + let left = node.left(); } @@ -239,6 +251,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn fix_insert_color(&self, node: &TreeNode) { + + // case 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); @@ -253,6 +267,10 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.fix_insert_color(&node.grandparent()); // case 4 } else if node.parent().color() == NodeColor::Red && node.uncle().color() == NodeColor::Black { + // if node == node.parent().right() && node.parent() == node.grandparent().left() { + // rotate_left(node); + // } + // else if node == node.parent // do some more stuff } else { // error handling here yay From b9e3e07e930d9df6f544384f06e96776e08df1b0 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 23:09:26 -0700 Subject: [PATCH 11/80] maybe fix height --- src/red_black_tree.rs | 58 +++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index c448d01..dc19c14 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::rc::Rc; -use std::f32; #[derive(Clone, Debug, PartialEq)] @@ -25,6 +24,7 @@ pub trait NodeTraits { fn new(val: T) -> TreeNode; fn unwrapped(&self) -> Rc>>; fn compare(&self, node: &TreeNode) -> bool; + fn node_height(&self) -> usize; fn color(&self) -> NodeColor; fn value(&self) -> Option; fn parent(&self) -> TreeNode; @@ -37,7 +37,6 @@ pub trait NodeTraits { fn set_parent(&mut self, parent: TreeNode); fn set_left(&mut self, left: TreeNode); fn set_right(&mut self, right: TreeNode); - fn node_height(&self) -> usize; } impl NodeTraits for TreeNode where T: Copy { @@ -66,6 +65,22 @@ impl NodeTraits for TreeNode where T: Copy { Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } + fn node_height(&self) -> usize { + match self { + Some(_) => { + let left_height = self.left().node_height(); + let right_height = self.right().node_height(); + + if left_height > right_height { + left_height + 1 + } else { + right_height + 1 + } + }, + None => 0 + } + } + fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -159,25 +174,6 @@ impl NodeTraits for TreeNode where T: Copy { }))) } } - - fn node_height(&self) -> usize { - - let left_height = match &*self { - Some(_) => self.left().node_height(), - None => 0, - }; - let right_height = match &*self { - Some(_) => self.right().node_height(), - None => 0, - }; - - if left_height > right_height { - left_height + 1 - } else { - right_height + 1 - } - - } } /******************** RBTree Helpers ********************/ @@ -211,16 +207,16 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - // TODO + // TODO ask miller if leaf nodes are included fn height(&self) -> usize { - - if self.len > 1 { - let length = self.len as f32; - length.log2() as usize - // self.root.node_height() - } else { - 0 - } + self.root.node_height() + + // use code below if leaf nodes are included + // if self.len >= 1 { + // self.root.node_height() + 1 + // } else { + // 0 + // } } fn is_empty(&self) -> bool { @@ -251,8 +247,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn fix_insert_color(&self, node: &TreeNode) { - - // case 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); From fef6da2d77462f55064e253bc8d609dd0f0bccde Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 20 Feb 2020 23:48:11 -0700 Subject: [PATCH 12/80] moved in_order_traversal to treenode --- src/red_black_tree.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index dc19c14..da9cddf 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -25,6 +25,7 @@ pub trait NodeTraits { fn unwrapped(&self) -> Rc>>; fn compare(&self, node: &TreeNode) -> bool; fn node_height(&self) -> usize; + fn print_traversal(&self); fn color(&self) -> NodeColor; fn value(&self) -> Option; fn parent(&self) -> TreeNode; @@ -39,7 +40,7 @@ pub trait NodeTraits { fn set_right(&mut self, right: TreeNode); } -impl NodeTraits for TreeNode where T: Copy { +impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { fn new(val: T) -> TreeNode { let tree_node = Some(Rc::new(RefCell::new(Node { color: NodeColor::Red, @@ -81,6 +82,18 @@ impl NodeTraits for TreeNode where T: Copy { } } + fn print_traversal(&self) { + if self.is_some() && self.value().is_some() { + self.left().print_traversal(); + if self.color() == NodeColor::Red { + print!("<{:?}>", self.value().unwrap()); + } else { + print!("[{:?}]", self.value().unwrap()); + } + self.right().print_traversal(); + } + } + fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -195,7 +208,6 @@ pub trait RBTreeTraits { fn fix_delete_color(&self, node: TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&self, value: T); - fn in_order_traversal(&self, node: &TreeNode); fn print(&self); } @@ -323,20 +335,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } - fn in_order_traversal(&self, node: &TreeNode) { - if node.is_some() && node.value().is_some() { - self.in_order_traversal(&node.left()); - if node.color() == NodeColor::Red { - print!("<{:?}>", node.value().unwrap()); - } else { - print!("[{:?}]", node.value().unwrap()); - } - self.in_order_traversal(&node.right()); - } - } - fn print(&self) { - self.in_order_traversal(&self.root); + self.root.print_traversal(); println!(); } } \ No newline at end of file From 243f75ba474479550d06fad8d218ec5f538f1bf4 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Fri, 21 Feb 2020 12:39:44 -0700 Subject: [PATCH 13/80] fix insert and rotate done --- src/main.rs | 42 ++++++++++++++- src/red_black_tree.rs | 116 ++++++++++++++++++++++++++++++++---------- 2 files changed, 129 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index 936ff4c..3796506 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,36 +21,76 @@ fn main() { println!("\n==== Start Testing RBTree Here ====\n"); let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); println!("empty height = {}", rbt.height()); + println!(); + println!("Inserting 5 ..."); rbt.insert_node(5); println!("size = {}", rbt.size()); rbt.print(); println!("height with 1 node = {}", rbt.height()); + println!(); // HEIGHTS ARE OFF BY ONE AND IDK WHY YET + println!("Inserting 70 ..."); rbt.insert_node(70); println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!(); + println!("Inserting 35 ..."); rbt.insert_node(35); println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!(); + println!("Inserting 8 ..."); rbt.insert_node(8); println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!(); + println!("Inserting 100 ..."); rbt.insert_node(100); println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!(); + println!("Inserting 60 ..."); rbt.insert_node(60); println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); - + println!(); + + println!("Inserting 120 ..."); + rbt.insert_node(120); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 1 ..."); + rbt.insert_node(1); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 84 ..."); + rbt.insert_node(84); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 17 ..."); + rbt.insert_node(17); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index da9cddf..5fd3b71 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -63,6 +63,9 @@ impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { } fn compare(&self, node: &TreeNode) -> bool { + if self.is_none() || node.is_none() { + return false + } Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } @@ -97,7 +100,7 @@ impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), - None => NodeColor::Red + None => NodeColor::Black // nil nodes are black } } @@ -134,7 +137,9 @@ impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { } fn uncle(&self) -> TreeNode { - if self.parent().compare(&self.grandparent().left()) { + if self.grandparent().left().is_none() || self.grandparent().right().is_none() { + None + } else if self.parent().compare(&self.grandparent().left()) { self.grandparent().right() } else { self.grandparent().left() @@ -202,12 +207,13 @@ pub trait RBTreeTraits { fn is_empty(&self) -> bool; fn size(&self) -> usize; fn contains(&self, value: T) -> bool; - fn rotate_left(&self, node: TreeNode); - fn rotate_right(&self, node: TreeNode); - fn fix_insert_color(&self, node: &TreeNode); - fn fix_delete_color(&self, node: TreeNode); + fn rotate_left(&mut self, node: &TreeNode); + fn rotate_right(&mut self, node: &TreeNode); + fn insert_case5(&mut self, node: &TreeNode); + fn fix_insert_color(&mut self, node: &TreeNode); + fn fix_delete_color(&mut self, node: &TreeNode); fn insert_node(&mut self, value: T); - fn delete_node(&self, value: T); + fn delete_node(&mut self, value: T); fn print(&self); } @@ -244,21 +250,71 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb false } - // TODO - fn rotate_left(&self, node: TreeNode) { - let parent = node.parent(); - let grandparent = node.grandparent(); - let left = node.left(); + fn rotate_left(&mut self, node: &TreeNode) { + let mut parent = node.parent().clone(); + let mut grandparent = node.grandparent().clone(); + let mut node = node.clone(); + + if parent.compare(&self.root) { + self.root = node.clone(); + } else { + node.set_parent(grandparent.clone()); + if parent.compare(&grandparent.left()) { + grandparent.set_left(node.clone()); + } else { + grandparent.set_right(node.clone()); + } + } + if node.left().is_some() { + node.left().set_parent(parent.clone()); + } + + parent.set_right(node.left().clone()); + node.set_left(parent.clone()); + parent.set_parent(node.clone()); } - // TODO - fn rotate_right(&self, node: TreeNode) { + fn rotate_right(&mut self, node: &TreeNode) { + let mut parent = node.parent().clone(); + let mut grandparent = node.grandparent().clone(); + let mut node = node.clone(); + + if parent.compare(&self.root) { + self.root = node.clone(); + } else { + node.set_parent(grandparent.clone()); + if parent.compare(&grandparent.left()) { + grandparent.set_left(node.clone()); + } else { + grandparent.set_right(node.clone()); + } + } + + if node.right().is_some() { + node.right().set_parent(parent.clone()); + } + parent.set_left(node.right().clone()); + node.set_right(parent.clone()); + parent.set_parent(node.clone()); } - // TODO - fn fix_insert_color(&self, node: &TreeNode) { + fn insert_case5(&mut self, node: &TreeNode) { + let parent = node.parent().clone(); + let grandparent = node.grandparent().clone(); + + if node.compare(&parent.left()) { + self.rotate_right(&parent); + } else { + self.rotate_left(&parent); + } + + parent.set_color(NodeColor::Black); + grandparent.set_color(NodeColor::Red); + } + + fn fix_insert_color(&mut self, node: &TreeNode) { // case 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); @@ -266,20 +322,23 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } else if node.parent().color() == NodeColor::Black { return; // case 3 - } else if node.parent().color() == NodeColor::Red && node.uncle().color() == NodeColor::Red { + } else if node.uncle().is_some() && node.uncle().color() == NodeColor::Red { node.parent().set_color(NodeColor::Black); node.uncle().set_color(NodeColor::Black); node.grandparent().set_color(NodeColor::Red); self.fix_insert_color(&node.grandparent()); // case 4 - } else if node.parent().color() == NodeColor::Red && node.uncle().color() == NodeColor::Black { - // if node == node.parent().right() && node.parent() == node.grandparent().left() { - // rotate_left(node); - // } - // else if node == node.parent - // do some more stuff - } else { - // error handling here yay + } else if node.uncle().color() == NodeColor::Black { // uncle can be a nil node + let parent = node.parent().clone(); + let grandparent = node.grandparent().clone(); + + if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { + self.rotate_left(&node); + self.insert_case5(&node.left()); + } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { + self.rotate_right(&node); + self.insert_case5(&node.right()); + } } } @@ -321,21 +380,22 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - // self.fix_insert_color(&new_node); + self.fix_insert_color(&new_node); self.len += 1; } // TODO - fn fix_delete_color(&self, node: TreeNode) { + fn fix_delete_color(&mut self, node: &TreeNode) { } // TODO - fn delete_node(&self, value: T) { + fn delete_node(&mut self, value: T) { } fn print(&self) { + println!("Root: {:?}", self.root.value().unwrap()); self.root.print_traversal(); println!(); } From d78831786a6b7f019c100a583b4c9cb24e44a02a Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Fri, 21 Feb 2020 13:01:33 -0700 Subject: [PATCH 14/80] rename --- src/red_black_tree.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 5fd3b71..9c29aad 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -206,7 +206,7 @@ pub trait RBTreeTraits { fn height(&self) -> usize; fn is_empty(&self) -> bool; fn size(&self) -> usize; - fn contains(&self, value: T) -> bool; + fn search(&self, value: T) -> TreeNode; fn rotate_left(&mut self, node: &TreeNode); fn rotate_right(&mut self, node: &TreeNode); fn insert_case5(&mut self, node: &TreeNode); @@ -245,9 +245,9 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len } - // TODO (extra thing i guess) - fn contains(&self, value: T) -> bool { - false + // TODO + fn search(&self, value: T) -> TreeNode { + None } fn rotate_left(&mut self, node: &TreeNode) { @@ -347,7 +347,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if self.is_empty() { self.root = new_node.clone(); - } else if self.contains(value) { + } else if self.search(value).is_some() { println!("Value already exists!"); return; } else { @@ -391,7 +391,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn delete_node(&mut self, value: T) { - + let mut node = self.search(value); } fn print(&self) { From 2438d2683596ac18cc003723626ff13d4e80bef2 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Fri, 21 Feb 2020 21:30:15 -0700 Subject: [PATCH 15/80] done search for nodes --- src/main.rs | 12 +++++++++++ src/red_black_tree.rs | 49 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3796506..b4c9791 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,4 +93,16 @@ fn main() { rbt.print(); println!("height = {}", rbt.height()); println!(); + + assert!(rbt.search(35).is_some()); + assert!(rbt.search(5).is_some()); + assert!(rbt.search(1).is_some()); + assert!(rbt.search(8).is_some()); + assert!(rbt.search(17).is_some()); + assert!(rbt.search(60).is_some()); + assert!(rbt.search(70).is_some()); + assert!(rbt.search(84).is_some()); + assert!(rbt.search(100).is_some()); + assert!(rbt.search(120).is_some()); + assert!(rbt.search(10).is_none()); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 9c29aad..ee084aa 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -38,9 +38,10 @@ pub trait NodeTraits { fn set_parent(&mut self, parent: TreeNode); fn set_left(&mut self, left: TreeNode); fn set_right(&mut self, right: TreeNode); + fn find_node(&self, value: T) -> TreeNode; } -impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { +impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Debug { fn new(val: T) -> TreeNode { let tree_node = Some(Rc::new(RefCell::new(Node { color: NodeColor::Red, @@ -192,6 +193,21 @@ impl NodeTraits for TreeNode where T: Copy + std::fmt::Debug { }))) } } + + fn find_node(&self, value: T) -> TreeNode { + match self { + Some(_) => { + if value == self.value().unwrap() { + self.clone() + } else if value < self.value().unwrap() { + self.left().find_node(value) + }else { + self.right().find_node(value) + } + }, + None => None + } + } } /******************** RBTree Helpers ********************/ @@ -245,9 +261,16 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len } - // TODO + // TODO: refactor because the code works but is bad lol fn search(&self, value: T) -> TreeNode { - None + + if self.root.is_none() { + return None + } else if self.root.value().unwrap() == value { + return self.root.clone() + } else { + self.root.find_node(value) + } } fn rotate_left(&mut self, node: &TreeNode) { @@ -391,7 +414,25 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO fn delete_node(&mut self, value: T) { - let mut node = self.search(value); + // let mut node = self.search(value); + + // if node.is_none() { + // return; + // } + + // if node.left().is_some() && node.right().is_some() { + // let mut larger = node.right(); + // let larger_value = larger.unwrapped(); + + // // larger.set_value(node.unwrapped()); + + // } + + // let old_node = node; + // // set node to null sibling + // if node.right().is_none() { + // node.set_value(node.left()); + // } } fn print(&self) { From 236ae146906bea5f1ee094404a6486697dc588d6 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sat, 22 Feb 2020 10:48:40 -0700 Subject: [PATCH 16/80] start cli --- src/main.rs | 230 ++++++++++++++++++++++++------------------ src/red_black_tree.rs | 10 +- src/tests.rs | 107 ++++++++++++++++++++ 3 files changed, 246 insertions(+), 101 deletions(-) create mode 100644 src/tests.rs diff --git a/src/main.rs b/src/main.rs index b4c9791..7853950 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,108 +1,142 @@ mod avl_tree; mod red_black_tree; +mod tests; use red_black_tree::*; +use tests::*; + +use std::io::{stdin, stdout, Write}; + +static MAIN_MENU:&str = " +1. Red Black Tree +2. AVL Tree +3. Run benchmark tests +4. Exit +"; + +static RBT_MENU: &str = " +1. Insert a node to the red-black tree +2. Delete a node from the red-black tree +3. Count the number of leaves in the tree +4. Return the height of the tree +5. Print in-order traversal of the tree +6. Check if tree is empty +7. Return to main menu +"; + +static AVL_MENU: &str = " +1. Insert a node to the AVL tree +2. Delete a node from the AVL tree +3. Count the number of leaves in the tree +4. Return the height of the tree +5. Print in-order traversal of the tree +6. Check if tree is empty +7. Return to main menu +"; + +fn get_value() -> u32 { + loop { + print!("Value: "); + stdout().flush().unwrap(); + let mut value = String::new(); + stdin().read_line(&mut value).expect("Failed to read line"); + + match value.trim().parse::() { + Ok(num) => return num, + Err(_) => continue + } + } +} -fn main() { - // Test TreeNode - let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); - - println!("{:?}", treenode.value()); - println!("{:?}", treenode.color()); - - treenode.set_color(red_black_tree::NodeColor::Black); - println!("{:?}", treenode.color()); +fn get_choice(num_items: u32) -> u32 { + loop { + print!("> "); + stdout().flush().unwrap(); + let mut choice = String::new(); + stdin().read_line(&mut choice).expect("Failed to read line"); + + let choice_parsed: u32 = match choice.trim().parse() { + Ok(num) => num, + Err(_) => continue + }; + + if num_items < choice_parsed { + println!("Invalid input"); + } else { + return choice_parsed; + } + } +} - treenode.set_value(10); - println!("{:?}", treenode.value()); +fn avl() { + print!("\nAVL TREE"); + + loop { + println!("{}", AVL_MENU); + let choice = get_choice(7); + match choice { + 1 => {}, + 2 => {}, + 3 => {}, + 4 => {}, + 5 => {}, + 6 => {}, + 7 => {}, + _ => println!("Invalid input!") + } + } +} +fn rbt() { + print!("\nRED-BLACK TREE"); - // Test RBTree - println!("\n==== Start Testing RBTree Here ====\n"); + // not sure what to use for type let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - println!("empty height = {}", rbt.height()); - println!(); - - println!("Inserting 5 ..."); - rbt.insert_node(5); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height with 1 node = {}", rbt.height()); - println!(); - - // HEIGHTS ARE OFF BY ONE AND IDK WHY YET - println!("Inserting 70 ..."); - rbt.insert_node(70); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 35 ..."); - rbt.insert_node(35); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 8 ..."); - rbt.insert_node(8); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 100 ..."); - rbt.insert_node(100); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 60 ..."); - rbt.insert_node(60); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 120 ..."); - rbt.insert_node(120); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 1 ..."); - rbt.insert_node(1); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 84 ..."); - rbt.insert_node(84); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 17 ..."); - rbt.insert_node(17); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - assert!(rbt.search(35).is_some()); - assert!(rbt.search(5).is_some()); - assert!(rbt.search(1).is_some()); - assert!(rbt.search(8).is_some()); - assert!(rbt.search(17).is_some()); - assert!(rbt.search(60).is_some()); - assert!(rbt.search(70).is_some()); - assert!(rbt.search(84).is_some()); - assert!(rbt.search(100).is_some()); - assert!(rbt.search(120).is_some()); - assert!(rbt.search(10).is_none()); + loop { + println!("{}", RBT_MENU); + let choice = get_choice(7); + match choice { + 1 => { + println!("\n[INSERT]"); + let value = get_value(); + rbt.insert_node(value); // TODO: error handling? + println!("Inserted {}", value); + }, + 2 => {}, + 3 => println!("{}", rbt.size()), + 4 => println!("{}", rbt.height()), + 5 => rbt.print(), + 6 => { + if rbt.is_empty() { + println!("Tree is empty."); + } else { + println!("nah tree is full of leaves"); + } + } + 7 => main_menu(), // would be nice to clear stack here + _ => println!("Invalid input!") + } + } +} + +fn main_menu() { + println!("{}", MAIN_MENU); + + loop { + let choice = get_choice(4); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => it_works(), + 4 => { + println!("ok bye"); + std::process::exit(0); + }, + _ => println!("Invalid input!") + } + } +} + +fn main() { + main_menu(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index ee084aa..995d89b 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -436,8 +436,12 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn print(&self) { - println!("Root: {:?}", self.root.value().unwrap()); - self.root.print_traversal(); - println!(); + if self.is_empty() { + println!("Tree is empty. Nothing to print."); + } else { + println!("Root: {:?}", self.root.value().unwrap()); + self.root.print_traversal(); + println!(); + } } } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..4222c8a --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,107 @@ +use super::*; + +// TODO: write actual tests lmao +// moved the stuff here to write the command line interface in main +pub fn it_works() { + // Test TreeNode + let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); + + println!("{:?}", treenode.value()); + println!("{:?}", treenode.color()); + + treenode.set_color(red_black_tree::NodeColor::Black); + println!("{:?}", treenode.color()); + + treenode.set_value(10); + println!("{:?}", treenode.value()); + + + // Test RBTree + println!("\n==== Start Testing RBTree Here ====\n"); + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + println!("empty height = {}", rbt.height()); + println!(); + + println!("Inserting 5 ..."); + rbt.insert_node(5); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height with 1 node = {}", rbt.height()); + println!(); + + // HEIGHTS ARE OFF BY ONE AND IDK WHY YET + println!("Inserting 70 ..."); + rbt.insert_node(70); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 35 ..."); + rbt.insert_node(35); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 8 ..."); + rbt.insert_node(8); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 100 ..."); + rbt.insert_node(100); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 60 ..."); + rbt.insert_node(60); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 120 ..."); + rbt.insert_node(120); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 1 ..."); + rbt.insert_node(1); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 84 ..."); + rbt.insert_node(84); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + println!("Inserting 17 ..."); + rbt.insert_node(17); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!(); + + assert!(rbt.search(35).is_some()); + assert!(rbt.search(5).is_some()); + assert!(rbt.search(1).is_some()); + assert!(rbt.search(8).is_some()); + assert!(rbt.search(17).is_some()); + assert!(rbt.search(60).is_some()); + assert!(rbt.search(70).is_some()); + assert!(rbt.search(84).is_some()); + assert!(rbt.search(100).is_some()); + assert!(rbt.search(120).is_some()); + assert!(rbt.search(10).is_none()); +} \ No newline at end of file From 3aaaf7eff91bd4a7d502f91e5411156ecb2a66b0 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sat, 22 Feb 2020 11:12:27 -0700 Subject: [PATCH 17/80] cleanup cli --- src/main.rs | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7853950..4fb52fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use tests::*; use std::io::{stdin, stdout, Write}; -static MAIN_MENU:&str = " +static MAIN_MENU: &str = " 1. Red Black Tree 2. AVL Tree 3. Run benchmark tests @@ -15,6 +15,7 @@ static MAIN_MENU:&str = " "; static RBT_MENU: &str = " +RED-BLACK TREE 1. Insert a node to the red-black tree 2. Delete a node from the red-black tree 3. Count the number of leaves in the tree @@ -25,6 +26,7 @@ static RBT_MENU: &str = " "; static AVL_MENU: &str = " +AVL TREE 1. Insert a node to the AVL tree 2. Delete a node from the AVL tree 3. Count the number of leaves in the tree @@ -34,9 +36,9 @@ static AVL_MENU: &str = " 7. Return to main menu "; -fn get_value() -> u32 { +fn get_input(prompt: &str) -> u32 { loop { - print!("Value: "); + print!("{} ", prompt); stdout().flush().unwrap(); let mut value = String::new(); stdin().read_line(&mut value).expect("Failed to read line"); @@ -48,32 +50,10 @@ fn get_value() -> u32 { } } -fn get_choice(num_items: u32) -> u32 { - loop { - print!("> "); - stdout().flush().unwrap(); - let mut choice = String::new(); - stdin().read_line(&mut choice).expect("Failed to read line"); - - let choice_parsed: u32 = match choice.trim().parse() { - Ok(num) => num, - Err(_) => continue - }; - - if num_items < choice_parsed { - println!("Invalid input"); - } else { - return choice_parsed; - } - } -} - fn avl() { - print!("\nAVL TREE"); - loop { println!("{}", AVL_MENU); - let choice = get_choice(7); + let choice = get_input(">"); match choice { 1 => {}, 2 => {}, @@ -88,17 +68,14 @@ fn avl() { } fn rbt() { - print!("\nRED-BLACK TREE"); - // not sure what to use for type let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); loop { println!("{}", RBT_MENU); - let choice = get_choice(7); + let choice = get_input(">"); match choice { 1 => { - println!("\n[INSERT]"); - let value = get_value(); + let value = get_input("Value to insert:"); rbt.insert_node(value); // TODO: error handling? println!("Inserted {}", value); }, @@ -123,7 +100,7 @@ fn main_menu() { println!("{}", MAIN_MENU); loop { - let choice = get_choice(4); + let choice = get_input(">"); match choice { 1 => rbt(), 2 => avl(), From 3c5cbb9fa7b1fde8adc2eab437b9ff67dc6c5a59 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sat, 22 Feb 2020 12:44:10 -0700 Subject: [PATCH 18/80] fix insert bug --- src/red_black_tree.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 995d89b..33884a8 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -354,14 +354,17 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } else if node.uncle().color() == NodeColor::Black { // uncle can be a nil node let parent = node.parent().clone(); let grandparent = node.grandparent().clone(); + let mut node = node.clone(); if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { self.rotate_left(&node); - self.insert_case5(&node.left()); + node = node.left().clone(); } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { self.rotate_right(&node); - self.insert_case5(&node.right()); + node = node.right().clone(); } + + self.insert_case5(&node); } } From 7e1c63ee1a3bf6ed345ac7884c8e8effe2f96bff Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sat, 22 Feb 2020 13:52:28 -0700 Subject: [PATCH 19/80] refactor rotate i guess --- src/main.rs | 2 +- src/red_black_tree.rs | 74 ++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4fb52fe..888a0f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,7 +69,7 @@ fn avl() { fn rbt() { // not sure what to use for type - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let mut rbt: RBTree = RBTree::new(); loop { println!("{}", RBT_MENU); let choice = get_input(">"); diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 33884a8..42c4e2e 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,6 +1,9 @@ use std::cell::RefCell; use std::rc::Rc; +static ROTATE_LEFT: bool = true; +static ROTATE_RIGHT: bool = false; + #[derive(Clone, Debug, PartialEq)] /******************** TreeNode Helpers ********************/ @@ -223,8 +226,7 @@ pub trait RBTreeTraits { fn is_empty(&self) -> bool; fn size(&self) -> usize; fn search(&self, value: T) -> TreeNode; - fn rotate_left(&mut self, node: &TreeNode); - fn rotate_right(&mut self, node: &TreeNode); + fn rotate(&mut self, node: &TreeNode, direction: bool); fn insert_case5(&mut self, node: &TreeNode); fn fix_insert_color(&mut self, node: &TreeNode); fn fix_delete_color(&mut self, node: &TreeNode); @@ -273,7 +275,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - fn rotate_left(&mut self, node: &TreeNode) { + fn rotate(&mut self, node: &TreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); let mut node = node.clone(); @@ -289,38 +291,20 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - if node.left().is_some() { - node.left().set_parent(parent.clone()); - } - - parent.set_right(node.left().clone()); - node.set_left(parent.clone()); parent.set_parent(node.clone()); - } - - fn rotate_right(&mut self, node: &TreeNode) { - let mut parent = node.parent().clone(); - let mut grandparent = node.grandparent().clone(); - let mut node = node.clone(); - - if parent.compare(&self.root) { - self.root = node.clone(); + if direction == ROTATE_LEFT { + if node.left().is_some() { + node.left().set_parent(parent.clone()); + } + parent.set_right(node.left().clone()); + node.set_left(parent.clone()); } else { - node.set_parent(grandparent.clone()); - if parent.compare(&grandparent.left()) { - grandparent.set_left(node.clone()); - } else { - grandparent.set_right(node.clone()); + if node.right().is_some() { + node.right().set_parent(parent.clone()); } + parent.set_left(node.right().clone()); + node.set_right(parent.clone()); } - - if node.right().is_some() { - node.right().set_parent(parent.clone()); - } - - parent.set_left(node.right().clone()); - node.set_right(parent.clone()); - parent.set_parent(node.clone()); } fn insert_case5(&mut self, node: &TreeNode) { @@ -328,9 +312,9 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb let grandparent = node.grandparent().clone(); if node.compare(&parent.left()) { - self.rotate_right(&parent); + self.rotate(&parent, ROTATE_RIGHT); } else { - self.rotate_left(&parent); + self.rotate(&parent, ROTATE_LEFT); } parent.set_color(NodeColor::Black); @@ -338,29 +322,31 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn fix_insert_color(&mut self, node: &TreeNode) { + let parent = node.parent().clone(); + let uncle = node.uncle().clone(); + let grandparent = node.grandparent().clone(); + // case 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); // case 2 - } else if node.parent().color() == NodeColor::Black { + } else if parent.color() == NodeColor::Black { return; // case 3 - } else if node.uncle().is_some() && node.uncle().color() == NodeColor::Red { - node.parent().set_color(NodeColor::Black); - node.uncle().set_color(NodeColor::Black); - node.grandparent().set_color(NodeColor::Red); - self.fix_insert_color(&node.grandparent()); + } else if uncle.is_some() && uncle.color() == NodeColor::Red { + parent.set_color(NodeColor::Black); + uncle.set_color(NodeColor::Black); + grandparent.set_color(NodeColor::Red); + self.fix_insert_color(&grandparent); // case 4 - } else if node.uncle().color() == NodeColor::Black { // uncle can be a nil node - let parent = node.parent().clone(); - let grandparent = node.grandparent().clone(); + } else if uncle.color() == NodeColor::Black { // uncle can be a nil node let mut node = node.clone(); if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { - self.rotate_left(&node); + self.rotate(&node, ROTATE_LEFT); node = node.left().clone(); } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { - self.rotate_right(&node); + self.rotate(&node, ROTATE_RIGHT); node = node.right().clone(); } From 51b6dbbb97cb3c6bd3abae07f8b3ed23241d9952 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sat, 22 Feb 2020 14:01:55 -0700 Subject: [PATCH 20/80] delete sort of --- src/red_black_tree.rs | 156 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 15 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 42c4e2e..fb85e68 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -233,6 +233,7 @@ pub trait RBTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); + fn get_higher_node(node: &TreeNode) -> TreeNode; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -396,32 +397,157 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len += 1; } - // TODO + // TODO - fill out commented code and actually test fn fix_delete_color(&mut self, node: &TreeNode) { + // case 1 + if node.parent().is_some() { + // find sibling + let sibling = match node.compare(&node.parent().left()) { + true => node.parent().right(), + false => node.parent().left(), + }; + + // case 2 + if sibling.color() == NodeColor::Red { + sibling.parent().set_color(NodeColor::Red); + sibling.set_color(NodeColor::Black); + + if node.compare(&node.parent().left()) { + // rotate_left(); + } else { + // rotate_right(); + } + + // update sibling + if node.compare(&node.parent().left()) { + // sibling = node.parent().right() + } else { + // sibling = node.parent().left() + } + } + + if sibling.left().is_some() && sibling.right().is_some() { + // case 3 + // there is was a super long IF statement so i broke it into a nested one + if node.parent().color() == NodeColor::Black && sibling.color() == NodeColor::Black { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { + sibling.set_color(NodeColor::Red); + self.fix_delete_color(&node.parent()); + } + } + // case 4 + else if node.parent().color() == NodeColor::Red && sibling.color() == NodeColor::Black { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { + sibling.set_color(NodeColor::Red); + node.parent().set_color(NodeColor::Black); + } + } + // case 5 + else { + if sibling.color() == NodeColor::Black { + if node.compare(&node.parent().left()) { + if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { + sibling.set_color(NodeColor::Red); + sibling.left().set_color(NodeColor::Black); + // rotate_right(sibling.left()); + } + } + else if node.compare(&node.parent().right()) { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Red { + sibling.set_color(NodeColor::Red); + sibling.right().set_color(NodeColor::Black); + // rotate_left(sibling.left()); + } + } + + // update sibling + if node.compare(&node.parent().left()) { + // sibling = node.parent().right(); + } else { + // sibling node.parent().left(); + } + } + + + // case 6 + sibling.set_color(node.parent().color()); + node.parent().set_color(NodeColor::Black); + if node.compare(&node.parent().left()) { + sibling.right().set_color(NodeColor::Black); + // rotate_left(sibling); + } else { + sibling.left().set_color(NodeColor::Black); + // rotate_right(sibling); + } + + } + } + } } + fn get_higher_node(node: &TreeNode) -> TreeNode { + if node.left().is_none() { + node.clone() + } else { + return Self::get_higher_node(&node.left()) + } + } // TODO fn delete_node(&mut self, value: T) { - // let mut node = self.search(value); + let mut node = self.search(value); - // if node.is_none() { - // return; - // } + if node.is_none() { + return; + } - // if node.left().is_some() && node.right().is_some() { - // let mut larger = node.right(); - // let larger_value = larger.unwrapped(); + if node.left().is_some() && node.right().is_some() { + let larger = Self::get_higher_node(&node.right()); - // // larger.set_value(node.unwrapped()); + let temp = larger.value(); + // TODO + // not sure how to set "larger"'s value to be the node value + // if there is a swap function from Rc or RefCell that would + // help a lot I think + // larger.set_value(node.unwrapped().clone()); + node.set_value(temp.unwrap()); + } - // } + let old_node = node.clone(); + // set node to null sibling + if node.right().is_none() { + node.set_value(node.left().value().unwrap()); + } else { + node.set_value(node.right().value().unwrap()); + } - // let old_node = node; - // // set node to null sibling - // if node.right().is_none() { - // node.set_value(node.left()); - // } + // link child to parent if node is not root + if !old_node.compare(&self.root) && old_node.parent().is_some() { + node.set_parent(old_node.parent()); + + if old_node.compare(&old_node.parent().left()) { + old_node.parent().set_left(node.clone()); + } else { + old_node.parent().set_right(node.clone()); + } + } else if node.is_none() { + // empty tree if child is None + self.root = None; + } else { + // set root to child + self.root.set_value(node.value().unwrap()); + node.set_parent(None); + } + + if old_node.color() == NodeColor::Black { + if node.color() == NodeColor::Red { + node.set_color(NodeColor::Black); + } else { + self.fix_delete_color(&node); + } + } + + self.len -= 1; } fn print(&self) { From e98bbb50f57527f04e8eacd29e2884c0c75c8031 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sat, 22 Feb 2020 22:57:33 -0700 Subject: [PATCH 21/80] replaced stuff with break statements --- src/main.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 888a0f4..7cd6c21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,7 +61,7 @@ fn avl() { 4 => {}, 5 => {}, 6 => {}, - 7 => {}, + 7 => break, _ => println!("Invalid input!") } } @@ -90,16 +90,15 @@ fn rbt() { println!("nah tree is full of leaves"); } } - 7 => main_menu(), // would be nice to clear stack here + 7 => break, _ => println!("Invalid input!") } } } -fn main_menu() { - println!("{}", MAIN_MENU); - +fn main() { loop { + println!("{}", MAIN_MENU); let choice = get_input(">"); match choice { 1 => rbt(), @@ -107,13 +106,9 @@ fn main_menu() { 3 => it_works(), 4 => { println!("ok bye"); - std::process::exit(0); + break; }, _ => println!("Invalid input!") } } } - -fn main() { - main_menu(); -} From 4a788ea1389e4cb03e2a4e6921f60d0c97f30f95 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 23 Feb 2020 15:29:04 -0700 Subject: [PATCH 22/80] todos and start counting leaves --- src/red_black_tree.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index fb85e68..9b738eb 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -204,7 +204,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb self.clone() } else if value < self.value().unwrap() { self.left().find_node(value) - }else { + } else { self.right().find_node(value) } }, @@ -234,6 +234,7 @@ pub trait RBTreeTraits { fn delete_node(&mut self, value: T); fn print(&self); fn get_higher_node(node: &TreeNode) -> TreeNode; + fn count_leaves(&self) -> usize; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -264,7 +265,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len } - // TODO: refactor because the code works but is bad lol fn search(&self, value: T) -> TreeNode { if self.root.is_none() { @@ -361,6 +361,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if self.is_empty() { self.root = new_node.clone(); } else if self.search(value).is_some() { + // TODO: should this just be a print? should we panic or do other stuff println!("Value already exists!"); return; } else { @@ -559,4 +560,16 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!(); } } + + // TODO count number of leaves + // maybe related to size() idk? + #[allow(unused_mut)] + fn count_leaves(&self) -> usize { + let mut num_leaves = 0; + // let mut curr_node = self.root; + // while curr_node.is_some() { + // if curr_node.left() + // } + num_leaves + } } \ No newline at end of file From 769b1a9f9ff73af974e41b37bd57a78cbcfe0753 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 23 Feb 2020 15:42:28 -0700 Subject: [PATCH 23/80] add comments --- src/red_black_tree.rs | 48 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 9b738eb..7bad798 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -24,11 +24,15 @@ pub struct Node { } pub trait NodeTraits { + // helper functions fn new(val: T) -> TreeNode; fn unwrapped(&self) -> Rc>>; fn compare(&self, node: &TreeNode) -> bool; + fn find_node(&self, value: T) -> TreeNode; fn node_height(&self) -> usize; fn print_traversal(&self); + + // getters for node properties and family members fn color(&self) -> NodeColor; fn value(&self) -> Option; fn parent(&self) -> TreeNode; @@ -36,12 +40,13 @@ pub trait NodeTraits { fn right(&self) -> TreeNode; fn grandparent(&self) -> TreeNode; fn uncle(&self) -> TreeNode; + + // setters for node properties fn set_color(&self, color: NodeColor); fn set_value(&self, value: T); fn set_parent(&mut self, parent: TreeNode); fn set_left(&mut self, left: TreeNode); fn set_right(&mut self, right: TreeNode); - fn find_node(&self, value: T) -> TreeNode; } impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Debug { @@ -73,6 +78,21 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } + fn find_node(&self, value: T) -> TreeNode { + match self { + Some(_) => { + if value == self.value().unwrap() { + self.clone() + } else if value < self.value().unwrap() { + self.left().find_node(value) + } else { + self.right().find_node(value) + } + }, + None => None + } + } + fn node_height(&self) -> usize { match self { Some(_) => { @@ -196,21 +216,6 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb }))) } } - - fn find_node(&self, value: T) -> TreeNode { - match self { - Some(_) => { - if value == self.value().unwrap() { - self.clone() - } else if value < self.value().unwrap() { - self.left().find_node(value) - } else { - self.right().find_node(value) - } - }, - None => None - } - } } /******************** RBTree Helpers ********************/ @@ -266,14 +271,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn search(&self, value: T) -> TreeNode { - - if self.root.is_none() { - return None - } else if self.root.value().unwrap() == value { - return self.root.clone() - } else { - self.root.find_node(value) - } + self.root.find_node(value) } fn rotate(&mut self, node: &TreeNode, direction: bool) { @@ -361,7 +359,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if self.is_empty() { self.root = new_node.clone(); } else if self.search(value).is_some() { - // TODO: should this just be a print? should we panic or do other stuff + // sticking with printing an err msg because panic causes the terminal to exit the program println!("Value already exists!"); return; } else { From e67486249d16fbdf0d343df7ce91b41d1b6f85b6 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 23 Feb 2020 18:50:53 -0700 Subject: [PATCH 24/80] done counting leaves --- src/red_black_tree.rs | 21 ++++++++++++--------- src/tests.rs | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 7bad798..0682a93 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -31,6 +31,7 @@ pub trait NodeTraits { fn find_node(&self, value: T) -> TreeNode; fn node_height(&self) -> usize; fn print_traversal(&self); + fn count_leaves(&self) -> usize; // getters for node properties and family members fn color(&self) -> NodeColor; @@ -216,6 +217,16 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb }))) } } + + fn count_leaves(&self) -> usize { + if self.is_none() { + 0 + } else if self.left().is_none() && self.right().is_none() { + 1 + } else { + self.left().count_leaves() + self.right().count_leaves() + } + } } /******************** RBTree Helpers ********************/ @@ -559,15 +570,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - // TODO count number of leaves - // maybe related to size() idk? - #[allow(unused_mut)] fn count_leaves(&self) -> usize { - let mut num_leaves = 0; - // let mut curr_node = self.root; - // while curr_node.is_some() { - // if curr_node.left() - // } - num_leaves + self.root.count_leaves() } } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 4222c8a..d8e621a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,7 +1,9 @@ use super::*; +#[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main +#[test] pub fn it_works() { // Test TreeNode let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); @@ -20,6 +22,7 @@ pub fn it_works() { println!("\n==== Start Testing RBTree Here ====\n"); let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); println!("empty height = {}", rbt.height()); + println!("no leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 5 ..."); @@ -27,6 +30,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height with 1 node = {}", rbt.height()); + println!("1 node = 1 leaf? = {}", rbt.count_leaves()); println!(); // HEIGHTS ARE OFF BY ONE AND IDK WHY YET @@ -42,6 +46,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("3 nodes = 2 leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 8 ..."); @@ -49,6 +54,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 100 ..."); @@ -56,6 +62,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 60 ..."); @@ -63,6 +70,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 120 ..."); @@ -70,6 +78,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 1 ..."); @@ -77,6 +86,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 84 ..."); @@ -84,6 +94,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); println!("Inserting 17 ..."); @@ -91,6 +102,7 @@ pub fn it_works() { println!("size = {}", rbt.size()); rbt.print(); println!("height = {}", rbt.height()); + println!("num leaves = {}", rbt.count_leaves()); println!(); assert!(rbt.search(35).is_some()); @@ -104,4 +116,6 @@ pub fn it_works() { assert!(rbt.search(100).is_some()); assert!(rbt.search(120).is_some()); assert!(rbt.search(10).is_none()); + + } \ No newline at end of file From 4d4842ec401b8757797a1d86104b80522dc923a9 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Wed, 26 Feb 2020 16:02:24 -0700 Subject: [PATCH 25/80] delete maybe --- src/red_black_tree.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 0682a93..ad1d037 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -424,15 +424,17 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb sibling.set_color(NodeColor::Black); if node.compare(&node.parent().left()) { - // rotate_left(); + self.rotate(&sibling, ROTATE_LEFT); } else { - // rotate_right(); + self.rotate(&sibling, ROTATE_RIGHT); } // update sibling if node.compare(&node.parent().left()) { + sibling.set_value(node.parent().right().value().unwrap()); // sibling = node.parent().right() } else { + sibling.set_value(node.parent().left().value().unwrap()); // sibling = node.parent().left() } } @@ -460,6 +462,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { sibling.set_color(NodeColor::Red); sibling.left().set_color(NodeColor::Black); + self.rotate(&sibling.left(), ROTATE_RIGHT); // rotate_right(sibling.left()); } } @@ -467,14 +470,17 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Red { sibling.set_color(NodeColor::Red); sibling.right().set_color(NodeColor::Black); + self.rotate(&sibling.left(), ROTATE_LEFT); // rotate_left(sibling.left()); } } // update sibling if node.compare(&node.parent().left()) { + sibling.set_value(node.parent().right().value().unwrap()); // sibling = node.parent().right(); } else { + sibling.set_value(node.parent().left().value().unwrap()); // sibling node.parent().left(); } } @@ -485,9 +491,11 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb node.parent().set_color(NodeColor::Black); if node.compare(&node.parent().left()) { sibling.right().set_color(NodeColor::Black); + self.rotate(&sibling, ROTATE_LEFT); // rotate_left(sibling); } else { sibling.left().set_color(NodeColor::Black); + self.rotate(&sibling, ROTATE_RIGHT); // rotate_right(sibling); } @@ -513,13 +521,10 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if node.left().is_some() && node.right().is_some() { let larger = Self::get_higher_node(&node.right()); - let temp = larger.value(); - // TODO - // not sure how to set "larger"'s value to be the node value - // if there is a swap function from Rc or RefCell that would - // help a lot I think - // larger.set_value(node.unwrapped().clone()); + let curr_val = node.value().unwrap(); + + larger.set_value(curr_val); node.set_value(temp.unwrap()); } From a5945eabc0ef933bd7ace6523afe341850803272 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Wed, 26 Feb 2020 19:47:50 -0700 Subject: [PATCH 26/80] delete without fixing color maybe work? --- src/main.rs | 29 ++++++------ src/red_black_tree.rs | 100 +++++++++++++++++++++++++++++++++++++----- src/tests.rs | 72 +++++++++++++++++++++++++++++- 3 files changed, 175 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7cd6c21..b249388 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,18 +97,19 @@ fn rbt() { } fn main() { - loop { - println!("{}", MAIN_MENU); - let choice = get_input(">"); - match choice { - 1 => rbt(), - 2 => avl(), - 3 => it_works(), - 4 => { - println!("ok bye"); - break; - }, - _ => println!("Invalid input!") - } - } + // loop { + // println!("{}", MAIN_MENU); + // let choice = get_input(">"); + // match choice { + // 1 => rbt(), + // 2 => avl(), + // 3 => it_works(), + // 4 => { + // println!("ok bye"); + // break; + // }, + // _ => println!("Invalid input!") + // } + // } + it_works(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index ad1d037..b589566 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::mem; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -15,6 +16,7 @@ pub enum NodeColor { pub type TreeNode = Option>>>; +#[derive(Debug)] pub struct Node { color: NodeColor, value: Option, @@ -32,6 +34,7 @@ pub trait NodeTraits { fn node_height(&self) -> usize; fn print_traversal(&self); fn count_leaves(&self) -> usize; + fn is_node_red(node: &TreeNode) -> bool; // getters for node properties and family members fn color(&self) -> NodeColor; @@ -41,6 +44,7 @@ pub trait NodeTraits { fn right(&self) -> TreeNode; fn grandparent(&self) -> TreeNode; fn uncle(&self) -> TreeNode; + // TODO: write getter for a sibling node // setters for node properties fn set_color(&self, color: NodeColor); @@ -227,6 +231,10 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb self.left().count_leaves() + self.right().count_leaves() } } + + fn is_node_red(node: &TreeNode) -> bool { + node.color() == NodeColor::Red + } } /******************** RBTree Helpers ********************/ @@ -246,6 +254,7 @@ pub trait RBTreeTraits { fn insert_case5(&mut self, node: &TreeNode); fn fix_insert_color(&mut self, node: &TreeNode); fn fix_delete_color(&mut self, node: &TreeNode); + fn fix_delete_color_2(&mut self, node: &TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); @@ -409,9 +418,11 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // TODO - fill out commented code and actually test fn fix_delete_color(&mut self, node: &TreeNode) { + println!("TRYING TO FIX DELETE COLOR"); // case 1 if node.parent().is_some() { + println!("CASE 1 TRYING TO FIX DELETE COLOR"); // find sibling let sibling = match node.compare(&node.parent().left()) { true => node.parent().right(), @@ -420,6 +431,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // case 2 if sibling.color() == NodeColor::Red { + println!("CASE 2 TRYING TO FIX DELETE COLOR"); sibling.parent().set_color(NodeColor::Red); sibling.set_color(NodeColor::Black); @@ -441,6 +453,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if sibling.left().is_some() && sibling.right().is_some() { // case 3 + println!("CASE 3 TRYING TO FIX DELETE COLOR"); // there is was a super long IF statement so i broke it into a nested one if node.parent().color() == NodeColor::Black && sibling.color() == NodeColor::Black { if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { @@ -451,12 +464,14 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // case 4 else if node.parent().color() == NodeColor::Red && sibling.color() == NodeColor::Black { if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { + println!("CASE 4 TRYING TO FIX DELETE COLOR"); sibling.set_color(NodeColor::Red); node.parent().set_color(NodeColor::Black); } } // case 5 else { + println!("CASE 5 TRYING TO FIX DELETE COLOR"); if sibling.color() == NodeColor::Black { if node.compare(&node.parent().left()) { if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { @@ -487,6 +502,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // case 6 + println!("CASE 6 TRYING TO FIX DELETE COLOR"); sibling.set_color(node.parent().color()); node.parent().set_color(NodeColor::Black); if node.compare(&node.parent().left()) { @@ -504,6 +520,49 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } + fn fix_delete_color_2(&mut self, node: &TreeNode) { + // case 1: node is root so done (it’s already black) + if node.compare(&self.root) { + return; + } + + // Case 2, sibling of node is red: + // Set parent’s color to red, and sibling’s color to black + // Rotate left/right on sibling if node is a lChild/rChild + // Update sibling to node’s new sibling + if node.parent().is_some() { + println!("case 2 delete"); + let mut sibling = match node.compare(&node.parent().left()) { + true => node.parent().right(), + false => node.parent().left(), + }; + + println!("SIBLING IS NOW: {:?}", sibling.value()); + + // actually start case 2 here: + if sibling.color() == NodeColor::Red { + sibling.parent().set_color(NodeColor::Red); + sibling.set_color(NodeColor::Black); + + if node.compare(&node.parent().left()) { + println!("LEFT ROTATING"); + self.rotate(&sibling, ROTATE_LEFT); + } else { + self.rotate(&sibling, ROTATE_RIGHT); + } + + if node.compare(&node.parent().left()) { + // THIS IS NOT WORKING? + // need to update the sibling to be node.parent.right? + sibling = node.parent().right().clone(); + } else { + sibling = node.parent().right().clone(); + } + + } + } + } + fn get_higher_node(node: &TreeNode) -> TreeNode { if node.left().is_none() { node.clone() @@ -520,45 +579,66 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } if node.left().is_some() && node.right().is_some() { - let larger = Self::get_higher_node(&node.right()); - let temp = larger.value(); - let curr_val = node.value().unwrap(); - - larger.set_value(curr_val); - node.set_value(temp.unwrap()); + let mut larger = Self::get_higher_node(&node.right()); + mem::swap(&mut node, &mut larger); + // let temp = larger.value(); + // let curr_val = node.value().unwrap(); + // larger.set_value(curr_val); + // node.set_value(temp.unwrap()); + + // node = larger.clone(); } let old_node = node.clone(); + println!("got old node == {:?}", old_node.value()); // set node to null sibling if node.right().is_none() { - node.set_value(node.left().value().unwrap()); + // println!("trying to set node.set_value(node.left().value().unwrap()) "); + // node.set_value(node.left().value()); + node = node.left().clone(); + println!("NODE RIGHT NONE SO NODE IS NOW = {:?}", node.value()); + } else { - node.set_value(node.right().value().unwrap()); + // println!("trying to set node.set_value(node.right().value().unwrap()); "); + node = node.right().clone(); + println!("NODE LEFT NONE SO NODE IS NOW = {:?}", node.value()); } + // If node is not root (parent not null) + // then link child to parent; otherwise: + // If child is NIL, then empty the tree + // Otherwise, set root to child + // link child to parent if node is not root + if !old_node.compare(&self.root) && old_node.parent().is_some() { + println!("old node != self root && old_node.parent() != none"); + println!("old node parent = {:?} and node parent = {:?}", old_node.parent().value(), node.parent().value()); node.set_parent(old_node.parent()); + println!("node parent now set to old node {:?}", node.parent().value()); if old_node.compare(&old_node.parent().left()) { old_node.parent().set_left(node.clone()); } else { old_node.parent().set_right(node.clone()); } + } else if node.is_none() { // empty tree if child is None self.root = None; } else { // set root to child - self.root.set_value(node.value().unwrap()); + self.root = node.clone(); node.set_parent(None); } if old_node.color() == NodeColor::Black { if node.color() == NodeColor::Red { + println!("dont need to fix color"); node.set_color(NodeColor::Black); } else { - self.fix_delete_color(&node); + println!("NEED TO FIX COLOR"); + self.fix_delete_color_2(&node); } } diff --git a/src/tests.rs b/src/tests.rs index d8e621a..8e6d1fa 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,9 +1,9 @@ use super::*; -#[cfg(test)] +// #[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main -#[test] +// #[test] pub fn it_works() { // Test TreeNode let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); @@ -117,5 +117,73 @@ pub fn it_works() { assert!(rbt.search(120).is_some()); assert!(rbt.search(10).is_none()); + // println!("Deleting 1 ..."); + // rbt.delete_node(1); + // println!("size = {}", rbt.size()); + // rbt.print(); + // println!("height = {}", rbt.height()); + // println!("num leaves = {}", rbt.count_leaves()); + // println!(); + + println!("\n==== Start Testing DELETE RBTree Here ====\n"); + let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + println!("Inserting 30 ..."); + rbt2.insert_node(30); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Inserting 20 ..."); + rbt2.insert_node(20); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Inserting 40 ..."); + rbt2.insert_node(40); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Inserting 10 ..."); + rbt2.insert_node(10); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Deleting 10 ..."); + rbt2.delete_node(10); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Inserting 50 ..."); + rbt2.insert_node(50); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + + println!("Deleting 20 ..."); + rbt2.delete_node(20); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); + + } \ No newline at end of file From cbec0c5f9764869db7b271c14e1580cf1cef147d Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Thu, 27 Feb 2020 09:09:39 -0700 Subject: [PATCH 27/80] avl node done? --- src/avl_tree.rs | 222 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index e69de29..9591364 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -0,0 +1,222 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::mem::{replace, swap}; +use std::cmp::max; + +// #[derive(Clone, Debug, PartialEq)] + +pub type AVLTreeNode = Option>>>; + +pub struct AVLNode { + value: Option, + parent: AVLTreeNode, + left: AVLTreeNode, + right: AVLTreeNode, + height: isize, +} + +pub trait NodeTraits { + fn new(val: T) -> AVLTreeNode; + fn unwrapped(&self) -> Rc>>; + fn compare(&self, node: &AVLTreeNode) -> bool; + // fn node_height(&self) -> usize; + fn print_traversal(&self); + // fn color(&self) -> NodeColor; + fn value(&self) -> Option; + fn parent(&self) -> AVLTreeNode; + fn left(&self) -> AVLTreeNode; + fn right(&self) -> AVLTreeNode; + fn height(&self) -> isize; // AVL + fn grandparent(&self) -> AVLTreeNode; + fn uncle(&self) -> AVLTreeNode; + fn recalc_height(&mut self); // AVL + fn set_value(&self, value: T); + fn set_parent(&mut self, parent: AVLTreeNode); + fn set_left(&mut self, left: AVLTreeNode); + fn set_right(&mut self, right: AVLTreeNode); + fn set_height(&self, value: isize); // AVL + fn find_node(&self, value: T) -> AVLTreeNode; +} + +impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + fn new(val: T) -> AVLTreeNode { + let tree_node = Some(Rc::new(RefCell::new(AVLNode { + value: Some(val), + parent: None, + left: None, + right: None, + height: 1, + }))); + tree_node.left().set_parent(tree_node.clone()); + tree_node.right().set_parent(tree_node.clone()); + tree_node + } + + fn unwrapped(&self) -> Rc>> { + match self { + Some(tree_node) => Rc::clone(&tree_node), + None => panic!("Error unwrapping tree node") + } + } + + fn compare(&self, node: &AVLTreeNode) -> bool { + if self.is_none() || node.is_none() { + return false + } + Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) + } + + // node_height + + fn print_traversal(&self) { + if self.is_some() && self.value().is_some() { + self.left().print_traversal(); + print!("{:?} ", self.value().unwrap()); + self.right().print_traversal(); + } + } + + fn value(&self) -> Option { + match self { + Some(tree_node) => tree_node.borrow().value, + None => None + } + } + + fn parent(&self) -> AVLTreeNode { + match self { + Some(tree_node) => tree_node.borrow().parent.clone(), + None => None + } + } + + fn left(&self) -> AVLTreeNode { + match self { + Some(tree_node) => tree_node.borrow().left.clone(), + None => None + } + } + + fn right(&self) -> AVLTreeNode { + match self { + Some(tree_node) => tree_node.borrow().right.clone(), + None => None + } + } + + fn height(&self) -> isize { + match self { + Some(tree_node) => tree_node.borrow().height, + None => 0 + } + } + + fn grandparent(&self) -> AVLTreeNode { + self.parent().parent() + } + + fn uncle(&self) -> AVLTreeNode { + if self.grandparent().left().is_none() || self.grandparent().right().is_none() { + None + } else if self.parent().compare(&self.grandparent().left()) { + self.grandparent().right() + } else { + self.grandparent().left() + } + } + + fn set_value(&self, value: T) { + self.unwrapped().borrow_mut().value = Some(value); + } + + fn set_parent(&mut self, parent: AVLTreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().parent = parent, + None => *self = Some(Rc::new(RefCell::new(AVLNode { + value: self.value(), + parent: parent, + left: self.left(), + right: self.right(), + height: self.height(), + }))) + } + } + + fn set_left(&mut self, left: AVLTreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().left = left, + None => *self = Some(Rc::new(RefCell::new(AVLNode { + value: self.value(), + parent: self.parent(), + left: left, + right: self.right(), + height: self.height(), + }))) + } + } + + fn set_right(&mut self, right: AVLTreeNode) { + match self { + Some(tree_node) => tree_node.borrow_mut().right = right, + None => *self = Some(Rc::new(RefCell::new(AVLNode { + value: self.value(), + parent: self.parent(), + left: self.left(), + right: right, + height: self.height(), + }))) + } + } + + fn set_height(&self, value: isize) { + self.unwrapped().borrow_mut().height = value; + } + + fn find_node(&self, value: T) -> AVLTreeNode { + match self { + Some(_) => { + if value == self.value().unwrap() { + self.clone() + } else if value < self.value().unwrap() { + self.left().find_node(value) + }else { + self.right().find_node(value) + } + }, + None => None + } + } + + fn recalc_height(&mut self) { + let left = self.left(); + let right = self.right(); + self.set_height(1 + max(left.height(), right.height())); + } +} + +// fn rotate_left(&mut self) { +// if self.right.is_none() { +// return +// } + +// let right_child = self.right.as_mut().unwrap().borrow(); +// let right_left = right_child.left.take(); +// let right_right = right_child.right.take(); + +// // Replace current right child with right grandchild +// let mut new_left_tree = replace(&mut self.right, right_right); +// swap(&mut self.value, &mut new_left_tree.as_mut().unwrap().borrow().value); + +// let left_tree = self.left.take(); +// let new_left_node = new_left_tree.as_mut().unwrap().borrow(); + +// new_left_node.right = right_left; +// new_left_node.left = left_tree; +// self.left = new_left_tree; + +// if let Some(node) = self.left.as_mut() { +// self.left.as_mut().unwrap().borrow().recalc_height(); +// } + +// self.recalc_height(); +// } \ No newline at end of file From 249259c223a5a53e68c3ac2ecb2f6beb33d5d5bf Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 11:42:56 -0700 Subject: [PATCH 28/80] fix deleting root lol --- src/red_black_tree.rs | 2 +- src/tests.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index b589566..8b4be6d 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -586,7 +586,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // larger.set_value(curr_val); // node.set_value(temp.unwrap()); - // node = larger.clone(); + node = larger.clone(); } let old_node = node.clone(); diff --git a/src/tests.rs b/src/tests.rs index 8e6d1fa..d67a8b1 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -184,6 +184,13 @@ pub fn it_works() { println!("num leaves = {}", rbt2.count_leaves()); println!(); + println!("Deleting 30 ..."); + rbt2.delete_node(30); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); } \ No newline at end of file From bb73533e7c32811cd5847a806609c63195b56765 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 12:02:14 -0700 Subject: [PATCH 29/80] done bst delete i guess --- src/red_black_tree.rs | 62 ++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 8b4be6d..073696a 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -579,66 +579,44 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } if node.left().is_some() && node.right().is_some() { - let mut larger = Self::get_higher_node(&node.right()); - mem::swap(&mut node, &mut larger); - // let temp = larger.value(); - // let curr_val = node.value().unwrap(); - // larger.set_value(curr_val); - // node.set_value(temp.unwrap()); - + let larger = Self::get_higher_node(&node.right()); + + node.set_value(larger.value().unwrap()); node = larger.clone(); } - let old_node = node.clone(); - println!("got old node == {:?}", old_node.value()); + println!("got old node == {:?}", node.value()); // set node to null sibling - if node.right().is_none() { - // println!("trying to set node.set_value(node.left().value().unwrap()) "); - // node.set_value(node.left().value()); - node = node.left().clone(); - println!("NODE RIGHT NONE SO NODE IS NOW = {:?}", node.value()); - - } else { - // println!("trying to set node.set_value(node.right().value().unwrap()); "); - node = node.right().clone(); - println!("NODE LEFT NONE SO NODE IS NOW = {:?}", node.value()); - } - - // If node is not root (parent not null) - // then link child to parent; otherwise: - // If child is NIL, then empty the tree - // Otherwise, set root to child + let mut child = match node.right() { + None => node.left().clone(), + Some(_) => node.right().clone(), + }; - // link child to parent if node is not root + if !node.compare(&self.root) && node.parent().is_some() { + child.set_parent(node.parent()); - if !old_node.compare(&self.root) && old_node.parent().is_some() { - println!("old node != self root && old_node.parent() != none"); - println!("old node parent = {:?} and node parent = {:?}", old_node.parent().value(), node.parent().value()); - node.set_parent(old_node.parent()); - println!("node parent now set to old node {:?}", node.parent().value()); - - if old_node.compare(&old_node.parent().left()) { - old_node.parent().set_left(node.clone()); + if node.compare(&node.parent().left()) { + node.parent().set_left(child.clone()); } else { - old_node.parent().set_right(node.clone()); + node.parent().set_right(child.clone()); } - } else if node.is_none() { + } else if child.is_none() { // empty tree if child is None self.root = None; } else { // set root to child - self.root = node.clone(); - node.set_parent(None); + self.root = child.clone(); + child.set_parent(None); } - if old_node.color() == NodeColor::Black { - if node.color() == NodeColor::Red { + if node.color() == NodeColor::Black { + if child.color() == NodeColor::Red { println!("dont need to fix color"); - node.set_color(NodeColor::Black); + child.set_color(NodeColor::Black); } else { println!("NEED TO FIX COLOR"); - self.fix_delete_color_2(&node); + self.fix_delete_color_2(&child); } } From 5aaffec09f41f0e5648391ae73e22f6368604672 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Thu, 27 Feb 2020 12:17:00 -0700 Subject: [PATCH 30/80] some cleanup --- src/red_black_tree.rs | 69 ++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 073696a..2af60b8 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::rc::Rc; -use std::mem; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -126,6 +125,20 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } + fn count_leaves(&self) -> usize { + if self.is_none() { + 0 + } else if self.left().is_none() && self.right().is_none() { + 1 + } else { + self.left().count_leaves() + self.right().count_leaves() + } + } + + fn is_node_red(node: &TreeNode) -> bool { + node.color() == NodeColor::Red + } + fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -221,20 +234,6 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb }))) } } - - fn count_leaves(&self) -> usize { - if self.is_none() { - 0 - } else if self.left().is_none() && self.right().is_none() { - 1 - } else { - self.left().count_leaves() + self.right().count_leaves() - } - } - - fn is_node_red(node: &TreeNode) -> bool { - node.color() == NodeColor::Red - } } /******************** RBTree Helpers ********************/ @@ -258,7 +257,6 @@ pub trait RBTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn get_higher_node(node: &TreeNode) -> TreeNode; fn count_leaves(&self) -> usize; } @@ -270,11 +268,11 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - // TODO ask miller if leaf nodes are included + // TODO ask miller if nil nodes are included fn height(&self) -> usize { self.root.node_height() - // use code below if leaf nodes are included + // use code below if nil nodes are included // if self.len >= 1 { // self.root.node_height() + 1 // } else { @@ -315,14 +313,14 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if node.left().is_some() { node.left().set_parent(parent.clone()); } - parent.set_right(node.left().clone()); - node.set_left(parent.clone()); + parent.set_right(node.left()); + node.set_left(parent); } else { if node.right().is_some() { node.right().set_parent(parent.clone()); } - parent.set_left(node.right().clone()); - node.set_right(parent.clone()); + parent.set_left(node.right()); + node.set_right(parent); } } @@ -363,10 +361,10 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { self.rotate(&node, ROTATE_LEFT); - node = node.left().clone(); + node = node.left(); } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { self.rotate(&node, ROTATE_RIGHT); - node = node.right().clone(); + node = node.right(); } self.insert_case5(&node); @@ -563,14 +561,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - fn get_higher_node(node: &TreeNode) -> TreeNode { - if node.left().is_none() { - node.clone() - } else { - return Self::get_higher_node(&node.left()) - } - } - // TODO fn delete_node(&mut self, value: T) { let mut node = self.search(value); @@ -579,28 +569,27 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } if node.left().is_some() && node.right().is_some() { - let larger = Self::get_higher_node(&node.right()); - + let mut larger = node.right(); + while larger.left().is_some() { + larger = larger.left(); + } node.set_value(larger.value().unwrap()); - node = larger.clone(); + node = larger; } - println!("got old node == {:?}", node.value()); // set node to null sibling let mut child = match node.right() { - None => node.left().clone(), - Some(_) => node.right().clone(), + Some(_) => node.right(), + None => node.left() }; if !node.compare(&self.root) && node.parent().is_some() { child.set_parent(node.parent()); - if node.compare(&node.parent().left()) { node.parent().set_left(child.clone()); } else { node.parent().set_right(child.clone()); } - } else if child.is_none() { // empty tree if child is None self.root = None; From b58a4dca3022a7ce8610b71fe7706d8695800850 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 13:37:58 -0700 Subject: [PATCH 31/80] delete? --- src/main.rs | 36 +++++++++------- src/red_black_tree.rs | 97 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 99 insertions(+), 34 deletions(-) diff --git a/src/main.rs b/src/main.rs index b249388..1b68a2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,11 @@ fn rbt() { rbt.insert_node(value); // TODO: error handling? println!("Inserted {}", value); }, - 2 => {}, + 2 => { + let value = get_input("Value to delete:"); + rbt.delete_node(value); // TODO: error handling? + println!("Deleted {}", value); + }, 3 => println!("{}", rbt.size()), 4 => println!("{}", rbt.height()), 5 => rbt.print(), @@ -97,19 +101,19 @@ fn rbt() { } fn main() { - // loop { - // println!("{}", MAIN_MENU); - // let choice = get_input(">"); - // match choice { - // 1 => rbt(), - // 2 => avl(), - // 3 => it_works(), - // 4 => { - // println!("ok bye"); - // break; - // }, - // _ => println!("Invalid input!") - // } - // } - it_works(); + loop { + println!("{}", MAIN_MENU); + let choice = get_input(">"); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => it_works(), + 4 => { + println!("ok bye"); + break; + }, + _ => println!("Invalid input!") + } + } + // it_works(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 073696a..682bf3c 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -44,7 +44,7 @@ pub trait NodeTraits { fn right(&self) -> TreeNode; fn grandparent(&self) -> TreeNode; fn uncle(&self) -> TreeNode; - // TODO: write getter for a sibling node + fn sibling(&self) -> TreeNode; // setters for node properties fn set_color(&self, color: NodeColor); @@ -175,6 +175,13 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } + fn sibling(&self) -> TreeNode { + match self.compare(&self.parent().left()) { + true => self.parent().right(), + false => self.parent().left(), + } + } + fn set_color(&self, color: NodeColor) { self.unwrapped().borrow_mut().color = color; } @@ -526,21 +533,19 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb return; } + let mut sibling = node.sibling(); + + println!("SIBLING IS NOW: {:?}", sibling.value()); + // Case 2, sibling of node is red: // Set parent’s color to red, and sibling’s color to black // Rotate left/right on sibling if node is a lChild/rChild // Update sibling to node’s new sibling if node.parent().is_some() { println!("case 2 delete"); - let mut sibling = match node.compare(&node.parent().left()) { - true => node.parent().right(), - false => node.parent().left(), - }; - - println!("SIBLING IS NOW: {:?}", sibling.value()); - // actually start case 2 here: if sibling.color() == NodeColor::Red { + sibling.parent().set_color(NodeColor::Red); sibling.set_color(NodeColor::Black); @@ -548,26 +553,82 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!("LEFT ROTATING"); self.rotate(&sibling, ROTATE_LEFT); } else { + println!("RIGHT ROTATING"); self.rotate(&sibling, ROTATE_RIGHT); } - if node.compare(&node.parent().left()) { - // THIS IS NOT WORKING? - // need to update the sibling to be node.parent.right? - sibling = node.parent().right().clone(); - } else { - sibling = node.parent().right().clone(); - } + // update sibling after rotating + sibling = node.sibling(); } } + + // CASE 3 + if node.parent().color() == NodeColor::Black && sibling.color() == NodeColor::Black { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { + println!("DELETE CASE 3"); + sibling.set_color(NodeColor::Red); + self.fix_delete_color_2(&node.parent()); + return; + } + } + // CASE 4 + if node.parent().color() == NodeColor::Red && sibling.color() == NodeColor::Black { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { + println!("DELETE CASE 4"); + sibling.set_color(NodeColor::Red); + node.parent().set_color(NodeColor::Black); + return; + } + } + + // CASE 5 + if sibling.color() == NodeColor::Black { + println!("DELETE CASE 5"); + sibling.set_color(NodeColor::Red); + if node.compare(&node.parent().left()) { + if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { + println!("DELETE CASE 5 - RIGHT ROTATE"); + sibling.left().set_color(NodeColor::Black); + self.rotate(&sibling.left(), ROTATE_RIGHT); + // rotate_right(sibling.left()); + } + } + else if node.compare(&node.parent().right()) { + if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Red { + println!("DELETE CASE 5 - LEFT ROTATE"); + sibling.right().set_color(NodeColor::Black); + self.rotate(&sibling.left(), ROTATE_LEFT); + // rotate_left(sibling.left()); + } + } + + // update sibling + sibling = node.sibling(); + } + + // CASE 6 + println!("DELETE CASE 6"); + sibling.set_color(node.parent().color()); + node.parent().set_color(NodeColor::Black); + + if node.compare(&node.parent().left()) { + sibling.right().set_color(NodeColor::Black); + self.rotate(&sibling, ROTATE_LEFT); + // rotate_left(sibling); + } else { + sibling.left().set_color(NodeColor::Black); + self.rotate(&sibling, ROTATE_RIGHT); + // rotate_right(sibling); + } + } fn get_higher_node(node: &TreeNode) -> TreeNode { - if node.left().is_none() { + if node.right().is_none() { node.clone() } else { - return Self::get_higher_node(&node.left()) + return Self::get_higher_node(&node.right()) } } // TODO @@ -579,7 +640,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } if node.left().is_some() && node.right().is_some() { - let larger = Self::get_higher_node(&node.right()); + let larger = Self::get_higher_node(&node.left()); node.set_value(larger.value().unwrap()); node = larger.clone(); From 5ad98a18ef99c4218efe85491f502212c968cf89 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 14:31:20 -0700 Subject: [PATCH 32/80] testing delete --- src/main.rs | 29 +++++++++++++++-------------- src/red_black_tree.rs | 34 ++++++++++++++++++++++++++++++++-- src/tests.rs | 22 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1b68a2b..5b1a79f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,19 +101,20 @@ fn rbt() { } fn main() { - loop { - println!("{}", MAIN_MENU); - let choice = get_input(">"); - match choice { - 1 => rbt(), - 2 => avl(), - 3 => it_works(), - 4 => { - println!("ok bye"); - break; - }, - _ => println!("Invalid input!") - } - } + // loop { + // println!("{}", MAIN_MENU); + // let choice = get_input(">"); + // match choice { + // 1 => rbt(), + // 2 => avl(), + // 3 => it_works(), + // 4 => { + // println!("ok bye"); + // break; + // }, + // _ => println!("Invalid input!") + // } + // } // it_works(); + print_test(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index aec6024..9fe5419 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::mem; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -85,8 +86,13 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb fn find_node(&self, value: T) -> TreeNode { match self { Some(_) => { + println!("FOUND SOME"); + println!("in value = {:?}", value); + println!("self.value = {:?}", self.value().unwrap()); if value == self.value().unwrap() { + println!("VALUE TO CLONE = {:?}", self.value()); self.clone() + } else if value < self.value().unwrap() { self.left().find_node(value) } else { @@ -265,6 +271,7 @@ pub trait RBTreeTraits { fn delete_node(&mut self, value: T); fn print(&self); fn count_leaves(&self) -> usize; + fn get_higher_node(node: &TreeNode) -> TreeNode; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -296,6 +303,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn search(&self, value: T) -> TreeNode { + println!("GOING INTO FIND NODE"); self.root.find_node(value) } @@ -622,27 +630,49 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } + fn get_higher_node(node: &TreeNode) -> TreeNode { + println!("in get_higher_node"); + if node.right().is_none() { + node.clone() + } else { + return Self::get_higher_node(&node.right()) + } + } + fn delete_node(&mut self, value: T) { + println!("ABOUT TO SEARCH"); let mut node = self.search(value); + println!("done search"); if node.is_none() { + println!("node is none"); return; } + println!("641"); if node.left().is_some() && node.right().is_some() { let mut larger = node.left(); // node.right() while larger.right().is_some() { // larger.left() + println!("656"); larger = larger.right(); // larger.left() } - node.set_value(larger.value().unwrap()); - node = larger; + println!("659"); + // let mut larger = Self::get_higher_node(&node.left()); + println!("trying to set value"); + // node.set_value(larger.value().unwrap()); + mem::swap(&mut node, &mut larger); + + node = larger.clone(); + println!("650"); } // set node to null sibling + println!("654"); let mut child = match node.right() { Some(_) => node.right(), None => node.left() }; + println!("659"); if !node.compare(&self.root) && node.parent().is_some() { child.set_parent(node.parent()); diff --git a/src/tests.rs b/src/tests.rs index d67a8b1..90e385c 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -192,5 +192,27 @@ pub fn it_works() { println!("num leaves = {}", rbt2.count_leaves()); println!(); + + + +} + +pub fn print_test() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + for x in 1..=10 { + rbt.insert_node(x); + println!("inserting ... {}", x); + } + + + rbt.delete_node(4); + // println!() + rbt.delete_node(6); + rbt.delete_node(8); + rbt.delete_node(1); + rbt.delete_node(5); + + rbt.print(); } \ No newline at end of file From e7e5d8b82c2da27c0b6279b6b82b6aa088aeedbd Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Thu, 27 Feb 2020 14:45:55 -0700 Subject: [PATCH 33/80] fixed bug --- src/red_black_tree.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 9fe5419..6ec7805 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -84,7 +84,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } fn find_node(&self, value: T) -> TreeNode { - match self { + match self.value() { Some(_) => { println!("FOUND SOME"); println!("in value = {:?}", value); @@ -660,8 +660,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // let mut larger = Self::get_higher_node(&node.left()); println!("trying to set value"); // node.set_value(larger.value().unwrap()); - mem::swap(&mut node, &mut larger); - + // mem::swap(&mut node, &mut larger); + mem::replace(&mut node.value(), larger.value()); node = larger.clone(); println!("650"); } From 19b26d74b999562879848ca0f5571bc88cbba6e3 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 16:13:10 -0700 Subject: [PATCH 34/80] =?UTF-8?q?DELETE=20=F0=9F=A4=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 3 +- src/red_black_tree.rs | 52 +++++++++++------ src/tests.rs | 44 ++++++++++++-- testhistory.txt | 132 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+), 23 deletions(-) create mode 100644 testhistory.txt diff --git a/src/main.rs b/src/main.rs index 5b1a79f..8dc279c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -116,5 +116,6 @@ fn main() { // } // } // it_works(); - print_test(); + // print_test(); + delete_cases_2_4(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 6ec7805..9036d74 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::rc::Rc; -use std::mem; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -541,8 +540,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb let mut sibling = node.sibling(); - println!("SIBLING IS NOW: {:?}", sibling.value()); - // Case 2, sibling of node is red: // Set parent’s color to red, and sibling’s color to black // Rotate left/right on sibling if node is a lChild/rChild @@ -640,39 +637,58 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn delete_node(&mut self, value: T) { - println!("ABOUT TO SEARCH"); let mut node = self.search(value); - println!("done search"); if node.is_none() { - println!("node is none"); return; } - println!("641"); - if node.left().is_some() && node.right().is_some() { + if node.left().value().is_some() && node.right().value().is_some() { let mut larger = node.left(); // node.right() - while larger.right().is_some() { // larger.left() - println!("656"); + println!("init larger = {:?}", larger.value()); + let mut temp = larger.clone(); + while larger.right().value().is_some() { // larger.left() + println!("======> larger in loop is = {:?}", larger.value()); larger = larger.right(); // larger.left() + temp = larger.parent(); } - println!("659"); + // larger = larger.parent(); + // larger = Self::get_higher_node(&node.left()); + // println!("USING GET LARGER FUNC LARGER ==== {:?} ", larger.value()); + + println!("larger is now = {:?}", larger.value()); + println!(">>>>>>>>>>>>>>>>> temp is now = {:?}", temp.value()); + // larger.set_value(temp.value().unwrap()); + println!(">>>>>>>>>>>>>>>>> LARGER IS NOW TEMP = {:?}", larger.value()); // let mut larger = Self::get_higher_node(&node.left()); - println!("trying to set value"); - // node.set_value(larger.value().unwrap()); + node.set_value(larger.value().unwrap()); + + println!("node value is now = {:?}", node.value()); // mem::swap(&mut node, &mut larger); - mem::replace(&mut node.value(), larger.value()); + // let temp = mem::replace(&mut node, larger); + // println!("larger after swapping with node = {:?}", temp.value()); + + // println!("temp = {:?}", temp); + // node = temp; node = larger.clone(); - println!("650"); + println!("node is now = {:?}", node.value()); + + // if value == 5 { + // process::exit(0); + // } + } // set node to null sibling - println!("654"); - let mut child = match node.right() { + + println!("setting node to null sibling now"); + println!("====== node is now = {:?}", node.value()); + let mut child = match node.left() { Some(_) => node.right(), None => node.left() }; - println!("659"); + + println!("child is now set to = {:?}", child.value()); if !node.compare(&self.root) && node.parent().is_some() { child.set_parent(node.parent()); diff --git a/src/tests.rs b/src/tests.rs index 90e385c..d76a471 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -197,7 +197,7 @@ pub fn it_works() { } -pub fn print_test() { +pub fn delete_cases_1_3_5_6() { let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); for x in 1..=10 { @@ -207,12 +207,48 @@ pub fn print_test() { rbt.delete_node(4); - // println!() + // rbt.print(); rbt.delete_node(6); + rbt.print(); rbt.delete_node(8); + // rbt.print(); rbt.delete_node(1); + rbt.print(); + // println!("-----------------------------PRINTING DELETING 5"); rbt.delete_node(5); - rbt.print(); + rbt.delete_node(9); + rbt.delete_node(2); + rbt.print(); + +} -} \ No newline at end of file +pub fn delete_cases_2_4() { + println!("\n==== Start Testing DELETE RBTree Here ====\n"); + + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + + for &x in vec_in.iter() { + println!("inserting {} ...", x); + rbt.insert_node(x); + println!("size is now = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!("leaves = {}", rbt.count_leaves()); + println!(); + } + + vec_in = vec![17, 84, 99, 5, 1, 60]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + rbt.delete_node(x); + println!("size is now = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!("leaves = {}", rbt.count_leaves()); + println!(); + } + + + } \ No newline at end of file diff --git a/testhistory.txt b/testhistory.txt new file mode 100644 index 0000000..5293d0b --- /dev/null +++ b/testhistory.txt @@ -0,0 +1,132 @@ +diff --git a/src/tests.rs b/src/tests.rs +index 8e6d1fa..c37f23c 100644 +--- a/src/tests.rs ++++ b/src/tests.rs +@@ -127,63 +127,99 @@ pub fn it_works() { + + println!("\n==== Start Testing DELETE RBTree Here ====\n"); + let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); ++ let mut vec_in: Vec = vec![30, 20, 40, 10]; ++ ++ for &x in vec_in.iter() { ++ println!("inserting {} ...", x); ++ rbt2.insert_node(x); ++ println!("size is now = {}", rbt2.size()); ++ rbt2.print(); ++ println!("height = {}", rbt2.height()); ++ println!("leaves = {}", rbt2.count_leaves()); ++ println!(); ++ } + +- println!("Inserting 30 ..."); +- rbt2.insert_node(30); ++ println!("Deleting 10 ..."); ++ rbt2.delete_node(10); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); +- println!("leaves = {}", rbt2.count_leaves()); ++ println!("num leaves = {}", rbt2.count_leaves()); + println!(); + +- println!("Inserting 20 ..."); +- rbt2.insert_node(20); ++ println!("Inserting 50 ..."); ++ rbt2.insert_node(50); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + +- println!("Inserting 40 ..."); +- rbt2.insert_node(40); ++ println!("Deleting 20 ..."); ++ rbt2.delete_node(20); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); +- println!("leaves = {}", rbt2.count_leaves()); ++ println!("num leaves = {}", rbt2.count_leaves()); + println!(); + +- println!("Inserting 10 ..."); +- rbt2.insert_node(10); +- println!("size = {}", rbt2.size()); +- rbt2.print(); +- println!("height = {}", rbt2.height()); +- println!("leaves = {}", rbt2.count_leaves()); +- println!(); ++ vec_in = vec![51, 52, 53, 54]; + +- println!("Deleting 10 ..."); +- rbt2.delete_node(10); +- println!("size = {}", rbt2.size()); +- rbt2.print(); +- println!("height = {}", rbt2.height()); +- println!("num leaves = {}", rbt2.count_leaves()); +- println!(); ++ for &x in vec_in.iter() { ++ println!("inserting {} ...", x); ++ rbt2.insert_node(x); ++ println!("size is now = {}", rbt2.size()); ++ rbt2.print(); ++ println!("height = {}", rbt2.height()); ++ println!("leaves = {}", rbt2.count_leaves()); ++ println!(); ++ } + +- println!("Inserting 50 ..."); +- rbt2.insert_node(50); ++ println!("Deleting 52 ..."); ++ rbt2.delete_node(52); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); +- println!("leaves = {}", rbt2.count_leaves()); ++ println!("num leaves = {}", rbt2.count_leaves()); + println!(); + +- println!("Deleting 20 ..."); +- rbt2.delete_node(20); ++ println!("Deleting 53 ..."); ++ rbt2.delete_node(53); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); ++ println!("{:?}", rbt2.root.value()); + ++} ++ +pub fn ray_delete_test() { + println!("\n==== Start Testing DELETE RBTree Here ====\n"); + + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + + for &x in vec_in.iter() { + println!("inserting {} ...", x); + rbt.insert_node(x); + println!("size is now = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!("leaves = {}", rbt.count_leaves()); + println!(); + } + + vec_in = vec![17, 84, 99, 5, 1]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + rbt.delete_node(x); + println!("size is now = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!("leaves = {}", rbt.count_leaves()); + println!(); + } + + + } +\ No newline at end of file From 7e3bcf77ab1915180c76ccc5718159ca648cd67d Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 19:17:47 -0700 Subject: [PATCH 35/80] clean up + make avl TODOs --- src/avl_tree.rs | 175 ++++++++++++++++++++++++++++++++++-------- src/red_black_tree.rs | 1 - 2 files changed, 141 insertions(+), 35 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 9591364..454427b 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -16,26 +16,33 @@ pub struct AVLNode { } pub trait NodeTraits { + // helper functions fn new(val: T) -> AVLTreeNode; fn unwrapped(&self) -> Rc>>; fn compare(&self, node: &AVLTreeNode) -> bool; - // fn node_height(&self) -> usize; + fn find_node(&self, value: T) -> AVLTreeNode; fn print_traversal(&self); - // fn color(&self) -> NodeColor; + fn count_leaves(&self) -> usize; + fn recalc_height(&mut self); // AVL + + // getters for node properties and family members + fn height(&self) -> isize; // AVL fn value(&self) -> Option; fn parent(&self) -> AVLTreeNode; fn left(&self) -> AVLTreeNode; fn right(&self) -> AVLTreeNode; - fn height(&self) -> isize; // AVL fn grandparent(&self) -> AVLTreeNode; fn uncle(&self) -> AVLTreeNode; - fn recalc_height(&mut self); // AVL + fn sibling(&self) -> AVLTreeNode; + + // setters for node properties + fn set_height(&self, value: isize); // AVL fn set_value(&self, value: T); fn set_parent(&mut self, parent: AVLTreeNode); fn set_left(&mut self, left: AVLTreeNode); fn set_right(&mut self, right: AVLTreeNode); - fn set_height(&self, value: isize); // AVL - fn find_node(&self, value: T) -> AVLTreeNode; + + } impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { @@ -66,7 +73,20 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } - // node_height + fn find_node(&self, value: T) -> AVLTreeNode { + match self { + Some(_) => { + if value == self.value().unwrap() { + self.clone() + } else if value < self.value().unwrap() { + self.left().find_node(value) + }else { + self.right().find_node(value) + } + }, + None => None + } + } fn print_traversal(&self) { if self.is_some() && self.value().is_some() { @@ -76,6 +96,29 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } + fn count_leaves(&self) -> usize { + if self.is_none() { + 0 + } else if self.left().is_none() && self.right().is_none() { + 1 + } else { + self.left().count_leaves() + self.right().count_leaves() + } + } + + fn recalc_height(&mut self) { + let left = self.left(); + let right = self.right(); + self.set_height(1 + max(left.height(), right.height())); + } + + fn height(&self) -> isize { + match self { + Some(tree_node) => tree_node.borrow().height, + None => 0 + } + } + fn value(&self) -> Option { match self { Some(tree_node) => tree_node.borrow().value, @@ -104,13 +147,6 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn height(&self) -> isize { - match self { - Some(tree_node) => tree_node.borrow().height, - None => 0 - } - } - fn grandparent(&self) -> AVLTreeNode { self.parent().parent() } @@ -125,6 +161,17 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } + fn sibling(&self) -> AVLTreeNode { + match self.compare(&self.parent().left()) { + true => self.parent().right(), + false => self.parent().left(), + } + } + + fn set_height(&self, value: isize) { + self.unwrapped().borrow_mut().height = value; + } + fn set_value(&self, value: T) { self.unwrapped().borrow_mut().value = Some(value); } @@ -168,32 +215,92 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn set_height(&self, value: isize) { - self.unwrapped().borrow_mut().height = value; - } +} - fn find_node(&self, value: T) -> AVLTreeNode { - match self { - Some(_) => { - if value == self.value().unwrap() { - self.clone() - } else if value < self.value().unwrap() { - self.left().find_node(value) - }else { - self.right().find_node(value) - } - }, - None => None +/******************** AVL Tree Helpers ********************/ + +pub struct AVLTree { + root: AVLTreeNode, +} + +pub trait AVLTreeTraits { + fn new() -> AVLTree; + fn height(&self) -> usize; + fn is_empty(&self) -> bool; + fn size(&self) -> usize; + fn search(&self, value: T) -> AVLTreeNode; + fn rotate(&mut self, node: &AVLTreeNode, direction: bool); + fn fix_insert_height(&mut self, node: &AVLTreeNode); + fn fix_delete_height(&mut self, node: &AVLTreeNode); + fn insert_node(&mut self, value: T); + fn delete_node(&mut self, value: T); + fn print(&self); + fn count_leaves(&self) -> usize; +} + +impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { + fn new() -> AVLTree { + AVLTree { + root: None, // IDK WHY THIS IS COMPLAINING } } - fn recalc_height(&mut self) { - let left = self.left(); - let right = self.right(); - self.set_height(1 + max(left.height(), right.height())); + fn height(&self) -> usize { + 0 } -} + fn is_empty(&self) -> bool { + self.root.is_none() + } + + // DO WE NEED SIZE? + fn size(&self) -> usize { + 1 + } + + fn search(&self, value: T) -> AVLTreeNode { + self.root.find_node(value) + } + + // TODO + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { + + } + + // TODO + fn fix_insert_height(&mut self, node: &AVLTreeNode) { + + } + + // TODO + fn fix_delete_height(&mut self, node: &AVLTreeNode) { + + } + + // TODO + fn insert_node(&mut self, value: T) { + + } + + // TODO + fn delete_node(&mut self, value: T) { + + } + + fn print(&self) { + if self.is_empty() { + println!("Tree is empty. Nothing to print."); + } else { + println!("Root: {:?}", self.root.value().unwrap()); + self.root.print_traversal(); + println!(); + } + } + + fn count_leaves(&self) -> usize { + self.root.count_leaves() + } +} // fn rotate_left(&mut self) { // if self.right.is_none() { // return diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 9036d74..18a6dd8 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -302,7 +302,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn search(&self, value: T) -> TreeNode { - println!("GOING INTO FIND NODE"); self.root.find_node(value) } From d8d41d2f46549b60896ca1ccceed352ae4faa4e8 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 19:26:02 -0700 Subject: [PATCH 36/80] BST for avl insert --- src/avl_tree.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 2 ++ src/tests.rs | 4 ++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 454427b..025cd16 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -241,7 +241,7 @@ pub trait AVLTreeTraits { impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { fn new() -> AVLTree { AVLTree { - root: None, // IDK WHY THIS IS COMPLAINING + root: None, } } @@ -269,7 +269,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn fix_insert_height(&mut self, node: &AVLTreeNode) { - + println!("inside fixing insert height"); } // TODO @@ -280,6 +280,49 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn insert_node(&mut self, value: T) { + // REGULAR BINARY SEARCH TREE INSERTION + let mut new_node = AVLTreeNode::new(value); + + if self.is_empty() { + self.root = new_node.clone(); + } + else if self.search(value).is_some() { + println!("Value already exists!"); + return; + } + + else { + let mut curr_node = self.root.clone(); + let mut curr_node_parent: AVLTreeNode = None; + let mut is_left_child = true; + + // find empty node + while curr_node.value().is_some() { + curr_node_parent = curr_node.clone(); + if value < curr_node.value().unwrap() { + curr_node = curr_node.left(); + is_left_child = true; + } else { + curr_node = curr_node.right(); + is_left_child = false; + } + } + + // place new_node in found spot + if curr_node_parent.is_some() { + new_node.set_parent(curr_node_parent); + if is_left_child { + new_node.parent().set_left(new_node.clone()); + } else { + new_node.parent().set_right(new_node.clone()); + } + } else { + panic!("Current node has no parent!"); + } + } + + // TODO: AVL REBALANCING HERE + self.fix_insert_height(&new_node); } // TODO diff --git a/src/main.rs b/src/main.rs index 8dc279c..6fd869f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -118,4 +118,6 @@ fn main() { // it_works(); // print_test(); delete_cases_2_4(); + + avl_test(); } diff --git a/src/tests.rs b/src/tests.rs index d76a471..1ee23c3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -251,4 +251,8 @@ pub fn delete_cases_2_4() { } + } + + pub fn avl_test() { + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); } \ No newline at end of file From 2aa72dddaf7d66f29b0fd50889012029389b3fad Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Thu, 27 Feb 2020 20:10:10 -0700 Subject: [PATCH 37/80] i guess rotate might work --- src/avl_tree.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 025cd16..87a072f 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -3,6 +3,9 @@ use std::rc::Rc; use std::mem::{replace, swap}; use std::cmp::max; +static ROTATE_LEFT: bool = true; +static ROTATE_RIGHT: bool = false; + // #[derive(Clone, Debug, PartialEq)] pub type AVLTreeNode = Option>>>; @@ -229,7 +232,8 @@ pub trait AVLTreeTraits { fn is_empty(&self) -> bool; fn size(&self) -> usize; fn search(&self, value: T) -> AVLTreeNode; - fn rotate(&mut self, node: &AVLTreeNode, direction: bool); + fn get_balance(node: &AVLTreeNode) -> isize; + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode; fn fix_insert_height(&mut self, node: &AVLTreeNode); fn fix_delete_height(&mut self, node: &AVLTreeNode); fn insert_node(&mut self, value: T); @@ -246,7 +250,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } fn height(&self) -> usize { - 0 + self.root.height() as usize } fn is_empty(&self) -> bool { @@ -262,14 +266,81 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D self.root.find_node(value) } + fn get_balance(node: &AVLTreeNode) -> isize { + if node.is_none() { + 0 + } else { + node.left().height() - node.right().height() + } + } + // TODO - fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode { + let mut parent = node.parent().clone(); + let mut grandparent = node.grandparent().clone(); + let mut node = node.clone(); + if parent.compare(&self.root) { + self.root = node.clone(); + } else { + node.set_parent(grandparent.clone()); + if parent.compare(&grandparent.left()) { + grandparent.set_left(node.clone()); + } else { + grandparent.set_right(node.clone()); + } + } + + parent.set_parent(node.clone()); + if direction == ROTATE_LEFT { + if node.left().is_some() { + node.left().set_parent(parent.clone()); + } + parent.set_right(node.left()); + node.set_left(parent); + } else { + if node.right().is_some() { + node.right().set_parent(parent.clone()); + } + parent.set_left(node.right()); + node.set_right(parent); + } + + node } // TODO fn fix_insert_height(&mut self, node: &AVLTreeNode) { - println!("inside fixing insert height"); + node.recalc_height(); + + let balance = Self::get_balance(node); + let node_val = node.value(); + + // Left Left Case + if balance > 1 && node_val < node.left().value() { + self.rotate(node, ROTATE_RIGHT); + return + } + + // Right Right Case + if balance < -1 && node_val > node.right().value() { + self.rotate(node, ROTATE_LEFT); + return + } + + // Left Right Case + if balance > 1 && node_val > node.left().value() { + node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); + self.rotate(node, ROTATE_RIGHT); + return + } + + // Right Left Case + if balance < -1 && node_val < node.right().value() { + node.set_right(self.rotate(&node.right(), ROTATE_RIGHT)); + self.rotate(node, ROTATE_LEFT); + return + } } // TODO From 03639c3f2421b062ecaf64d8e88d4e3ba1525d82 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 20:18:18 -0700 Subject: [PATCH 38/80] clean up comments --- src/main.rs | 2 +- src/red_black_tree.rs | 169 ++---------------------------------------- src/tests.rs | 2 +- 3 files changed, 10 insertions(+), 163 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6fd869f..7bc4673 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,5 +119,5 @@ fn main() { // print_test(); delete_cases_2_4(); - avl_test(); + // avl_test(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 18a6dd8..85a0903 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -33,7 +33,7 @@ pub trait NodeTraits { fn node_height(&self) -> usize; fn print_traversal(&self); fn count_leaves(&self) -> usize; - fn is_node_red(node: &TreeNode) -> bool; + fn is_node_red(node: &TreeNode) -> bool; // TODO: replace comparing colors with this function // getters for node properties and family members fn color(&self) -> NodeColor; @@ -85,13 +85,8 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb fn find_node(&self, value: T) -> TreeNode { match self.value() { Some(_) => { - println!("FOUND SOME"); - println!("in value = {:?}", value); - println!("self.value = {:?}", self.value().unwrap()); if value == self.value().unwrap() { - println!("VALUE TO CLONE = {:?}", self.value()); self.clone() - } else if value < self.value().unwrap() { self.left().find_node(value) } else { @@ -265,12 +260,10 @@ pub trait RBTreeTraits { fn insert_case5(&mut self, node: &TreeNode); fn fix_insert_color(&mut self, node: &TreeNode); fn fix_delete_color(&mut self, node: &TreeNode); - fn fix_delete_color_2(&mut self, node: &TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); fn count_leaves(&self) -> usize; - fn get_higher_node(node: &TreeNode) -> TreeNode; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -427,111 +420,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len += 1; } - // TODO - fill out commented code and actually test fn fix_delete_color(&mut self, node: &TreeNode) { - println!("TRYING TO FIX DELETE COLOR"); - - // case 1 - if node.parent().is_some() { - println!("CASE 1 TRYING TO FIX DELETE COLOR"); - // find sibling - let sibling = match node.compare(&node.parent().left()) { - true => node.parent().right(), - false => node.parent().left(), - }; - - // case 2 - if sibling.color() == NodeColor::Red { - println!("CASE 2 TRYING TO FIX DELETE COLOR"); - sibling.parent().set_color(NodeColor::Red); - sibling.set_color(NodeColor::Black); - - if node.compare(&node.parent().left()) { - self.rotate(&sibling, ROTATE_LEFT); - } else { - self.rotate(&sibling, ROTATE_RIGHT); - } - - // update sibling - if node.compare(&node.parent().left()) { - sibling.set_value(node.parent().right().value().unwrap()); - // sibling = node.parent().right() - } else { - sibling.set_value(node.parent().left().value().unwrap()); - // sibling = node.parent().left() - } - } - - if sibling.left().is_some() && sibling.right().is_some() { - // case 3 - println!("CASE 3 TRYING TO FIX DELETE COLOR"); - // there is was a super long IF statement so i broke it into a nested one - if node.parent().color() == NodeColor::Black && sibling.color() == NodeColor::Black { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { - sibling.set_color(NodeColor::Red); - self.fix_delete_color(&node.parent()); - } - } - // case 4 - else if node.parent().color() == NodeColor::Red && sibling.color() == NodeColor::Black { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { - println!("CASE 4 TRYING TO FIX DELETE COLOR"); - sibling.set_color(NodeColor::Red); - node.parent().set_color(NodeColor::Black); - } - } - // case 5 - else { - println!("CASE 5 TRYING TO FIX DELETE COLOR"); - if sibling.color() == NodeColor::Black { - if node.compare(&node.parent().left()) { - if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { - sibling.set_color(NodeColor::Red); - sibling.left().set_color(NodeColor::Black); - self.rotate(&sibling.left(), ROTATE_RIGHT); - // rotate_right(sibling.left()); - } - } - else if node.compare(&node.parent().right()) { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Red { - sibling.set_color(NodeColor::Red); - sibling.right().set_color(NodeColor::Black); - self.rotate(&sibling.left(), ROTATE_LEFT); - // rotate_left(sibling.left()); - } - } - - // update sibling - if node.compare(&node.parent().left()) { - sibling.set_value(node.parent().right().value().unwrap()); - // sibling = node.parent().right(); - } else { - sibling.set_value(node.parent().left().value().unwrap()); - // sibling node.parent().left(); - } - } - - - // case 6 - println!("CASE 6 TRYING TO FIX DELETE COLOR"); - sibling.set_color(node.parent().color()); - node.parent().set_color(NodeColor::Black); - if node.compare(&node.parent().left()) { - sibling.right().set_color(NodeColor::Black); - self.rotate(&sibling, ROTATE_LEFT); - // rotate_left(sibling); - } else { - sibling.left().set_color(NodeColor::Black); - self.rotate(&sibling, ROTATE_RIGHT); - // rotate_right(sibling); - } - - } - } - } - } - - fn fix_delete_color_2(&mut self, node: &TreeNode) { // case 1: node is root so done (it’s already black) if node.compare(&self.root) { return; @@ -544,7 +433,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // Rotate left/right on sibling if node is a lChild/rChild // Update sibling to node’s new sibling if node.parent().is_some() { - println!("case 2 delete"); + println!("DELETE CASE 2"); // actually start case 2 here: if sibling.color() == NodeColor::Red { @@ -552,10 +441,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb sibling.set_color(NodeColor::Black); if node.compare(&node.parent().left()) { - println!("LEFT ROTATING"); self.rotate(&sibling, ROTATE_LEFT); } else { - println!("RIGHT ROTATING"); self.rotate(&sibling, ROTATE_RIGHT); } @@ -570,7 +457,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { println!("DELETE CASE 3"); sibling.set_color(NodeColor::Red); - self.fix_delete_color_2(&node.parent()); + self.fix_delete_color(&node.parent()); return; } } @@ -586,7 +473,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 5 if sibling.color() == NodeColor::Black { - println!("DELETE CASE 5"); sibling.set_color(NodeColor::Red); if node.compare(&node.parent().left()) { if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { @@ -626,15 +512,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } - fn get_higher_node(node: &TreeNode) -> TreeNode { - println!("in get_higher_node"); - if node.right().is_none() { - node.clone() - } else { - return Self::get_higher_node(&node.right()) - } - } - fn delete_node(&mut self, value: T) { let mut node = self.search(value); @@ -643,52 +520,22 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } if node.left().value().is_some() && node.right().value().is_some() { - let mut larger = node.left(); // node.right() - println!("init larger = {:?}", larger.value()); - let mut temp = larger.clone(); + let mut larger = node.left(); + while larger.right().value().is_some() { // larger.left() - println!("======> larger in loop is = {:?}", larger.value()); larger = larger.right(); // larger.left() - temp = larger.parent(); } - // larger = larger.parent(); - // larger = Self::get_higher_node(&node.left()); - // println!("USING GET LARGER FUNC LARGER ==== {:?} ", larger.value()); - - println!("larger is now = {:?}", larger.value()); - println!(">>>>>>>>>>>>>>>>> temp is now = {:?}", temp.value()); - // larger.set_value(temp.value().unwrap()); - println!(">>>>>>>>>>>>>>>>> LARGER IS NOW TEMP = {:?}", larger.value()); - // let mut larger = Self::get_higher_node(&node.left()); - node.set_value(larger.value().unwrap()); - - println!("node value is now = {:?}", node.value()); - // mem::swap(&mut node, &mut larger); - // let temp = mem::replace(&mut node, larger); - // println!("larger after swapping with node = {:?}", temp.value()); - // println!("temp = {:?}", temp); - // node = temp; + node.set_value(larger.value().unwrap()); node = larger.clone(); - println!("node is now = {:?}", node.value()); - - // if value == 5 { - // process::exit(0); - // } - } // set node to null sibling - - println!("setting node to null sibling now"); - println!("====== node is now = {:?}", node.value()); let mut child = match node.left() { Some(_) => node.right(), None => node.left() }; - println!("child is now set to = {:?}", child.value()); - if !node.compare(&self.root) && node.parent().is_some() { child.set_parent(node.parent()); if node.compare(&node.parent().left()) { @@ -710,8 +557,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!("dont need to fix color"); child.set_color(NodeColor::Black); } else { - println!("NEED TO FIX COLOR"); - self.fix_delete_color_2(&child); + println!("Fixing Color"); + self.fix_delete_color(&child); } } diff --git a/src/tests.rs b/src/tests.rs index 1ee23c3..52aefc4 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -254,5 +254,5 @@ pub fn delete_cases_2_4() { } pub fn avl_test() { - let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + // let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); } \ No newline at end of file From 38aac1012430b91755bb6cf6a47aa18691f0104d Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 20:54:39 -0700 Subject: [PATCH 39/80] add rbt benchmark + contains --- src/red_black_tree.rs | 8 ++++++++ src/tests.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 85a0903..a9db504 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -264,6 +264,7 @@ pub trait RBTreeTraits { fn delete_node(&mut self, value: T); fn print(&self); fn count_leaves(&self) -> usize; + fn contains(&self, value: T) -> bool; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -298,6 +299,13 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.root.find_node(value) } + fn contains(&self, value: T) -> bool { + match self.search(value) { + Some(_) => true, + None => false + } + } + fn rotate(&mut self, node: &TreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); diff --git a/src/tests.rs b/src/tests.rs index 52aefc4..753b725 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -4,6 +4,27 @@ use super::*; // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main // #[test] +pub fn benchmark_redblack() { + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let mut tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + for i in 0..tree_size { + tree.insert_node(i); + } + + let time = std::time::Instant::now(); + + for i in 0..tree_size/10 { + match tree.contains(i) { + true => { }, + false => println!("nope"), + } + } + + println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); + } +} + pub fn it_works() { // Test TreeNode let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); @@ -117,6 +138,18 @@ pub fn it_works() { assert!(rbt.search(120).is_some()); assert!(rbt.search(10).is_none()); + assert!(rbt.contains(35) == true); + assert!(rbt.contains(5) == true); + assert!(rbt.contains(1) == true); + assert!(rbt.contains(8) == true); + assert!(rbt.contains(17) == true); + assert!(rbt.contains(60) == true); + assert!(rbt.contains(70) == true); + assert!(rbt.contains(84) == true); + assert!(rbt.contains(100) == true); + assert!(rbt.contains(120) == true); + assert!(rbt.contains(10) == false); + // println!("Deleting 1 ..."); // rbt.delete_node(1); // println!("size = {}", rbt.size()); @@ -249,6 +282,8 @@ pub fn delete_cases_2_4() { println!("leaves = {}", rbt.count_leaves()); println!(); } + + } From 5914dc569e41d2eeaa537a85e9e13d9544bacc51 Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Thu, 27 Feb 2020 21:58:32 -0700 Subject: [PATCH 40/80] stack overflow --- src/avl_tree.rs | 37 +++++++++++++++++++++++++++++-------- src/tests.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 87a072f..a289bcb 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -6,10 +6,10 @@ use std::cmp::max; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; -// #[derive(Clone, Debug, PartialEq)] pub type AVLTreeNode = Option>>>; +#[derive(Clone, Debug, PartialEq)] pub struct AVLNode { value: Option, parent: AVLTreeNode, @@ -79,11 +79,15 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: fn find_node(&self, value: T) -> AVLTreeNode { match self { Some(_) => { + println!("hehe2"); if value == self.value().unwrap() { + println!("hehe2.1"); self.clone() } else if value < self.value().unwrap() { + println!("hehe2.2"); self.left().find_node(value) }else { + println!("hehe2.3"); self.right().find_node(value) } }, @@ -221,7 +225,7 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } /******************** AVL Tree Helpers ********************/ - +#[derive(Clone, Debug, PartialEq)] pub struct AVLTree { root: AVLTreeNode, } @@ -234,7 +238,7 @@ pub trait AVLTreeTraits { fn search(&self, value: T) -> AVLTreeNode; fn get_balance(node: &AVLTreeNode) -> isize; fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode; - fn fix_insert_height(&mut self, node: &AVLTreeNode); + fn fix_insert_height(&mut self, node: &mut AVLTreeNode); fn fix_delete_height(&mut self, node: &AVLTreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); @@ -276,6 +280,20 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode { + // let mut v = node.right(); + // if direction == ROTATE_RIGHT { + // v = node.left(); + // } + + // v.set_parent(node.parent()); + + // if direction == ROTATE_LEFT { + // node.set_right(v.left()); + // match node.right() { + // Some(tree_node) => node.right().set_parent(*node), + // } + // } + let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); let mut node = node.clone(); @@ -310,8 +328,12 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } // TODO - fn fix_insert_height(&mut self, node: &AVLTreeNode) { + fn fix_insert_height(&mut self, node: &mut AVLTreeNode) { node.recalc_height(); + + if node.parent().is_some() { + self.fix_insert_height(&mut node.parent()); + } let balance = Self::get_balance(node); let node_val = node.value(); @@ -353,9 +375,9 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // REGULAR BINARY SEARCH TREE INSERTION let mut new_node = AVLTreeNode::new(value); - if self.is_empty() { self.root = new_node.clone(); + return } else if self.search(value).is_some() { println!("Value already exists!"); @@ -366,7 +388,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D let mut curr_node = self.root.clone(); let mut curr_node_parent: AVLTreeNode = None; let mut is_left_child = true; - // find empty node while curr_node.value().is_some() { curr_node_parent = curr_node.clone(); @@ -378,7 +399,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D is_left_child = false; } } - + // place new_node in found spot if curr_node_parent.is_some() { new_node.set_parent(curr_node_parent); @@ -393,7 +414,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } // TODO: AVL REBALANCING HERE - self.fix_insert_height(&new_node); + self.fix_insert_height(&mut new_node); } // TODO diff --git a/src/tests.rs b/src/tests.rs index 753b725..7c3e21e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,5 +1,5 @@ use super::*; - +use avl_tree::AVLTreeTraits; // #[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main @@ -290,4 +290,31 @@ pub fn delete_cases_2_4() { pub fn avl_test() { // let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + //let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + + println!("\n==== Start Testing AVLTree Here ====\n"); + + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + println!("AVL Tree INIT = {:?}", avl); + for &x in vec_in.iter() { + println!("inserting {} ...", x); + avl.insert_node(x); + println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + } + + vec_in = vec![17, 84, 99, 5, 1, 60]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + avl.delete_node(x); + println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + } } \ No newline at end of file From ce510c352bc576d71d6a629f6b97a9a78d737dbb Mon Sep 17 00:00:00 2001 From: raysarinas Date: Thu, 27 Feb 2020 22:16:43 -0700 Subject: [PATCH 41/80] add contains and benchmark for avl --- src/avl_tree.rs | 10 +++++++++- src/tests.rs | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index a289bcb..490560a 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -244,6 +244,7 @@ pub trait AVLTreeTraits { fn delete_node(&mut self, value: T); fn print(&self); fn count_leaves(&self) -> usize; + fn contains(&self, value: T) -> bool; } impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -434,7 +435,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn count_leaves(&self) -> usize { self.root.count_leaves() - } + } + + fn contains(&self, value: T) -> bool { + match self.search(value) { + Some(_) => true, + None => false + } + } } // fn rotate_left(&mut self) { // if self.right.is_none() { diff --git a/src/tests.rs b/src/tests.rs index 7c3e21e..8a7989c 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -25,6 +25,27 @@ pub fn benchmark_redblack() { } } +pub fn benchmark_avl() { + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let mut tree: avl_tree::AVLTree = avl_tree::AVLTree::new(); + + for i in 0..tree_size { + tree.insert_node(i); + } + + let time = std::time::Instant::now(); + + for i in 0..tree_size/10 { + match tree.contains(i) { + true => { }, + false => println!("nope"), + } + } + + println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); + } +} + pub fn it_works() { // Test TreeNode let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); From 1a375921bfeeae7cb41cfa519d8b1b8667d45777 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Fri, 28 Feb 2020 00:25:08 -0700 Subject: [PATCH 42/80] add draft of design doc --- design_doc_draft.txt | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 design_doc_draft.txt diff --git a/design_doc_draft.txt b/design_doc_draft.txt new file mode 100644 index 0000000..0b51f75 --- /dev/null +++ b/design_doc_draft.txt @@ -0,0 +1,48 @@ +A design document outlining: +- Major innovations – Additional to the project specification. +- A detailed rationale for your augmented decisions with regard to the above design +questions. +- A list of known errors, faults, defects, missing functionality, etc. Telling us about +your system’s limitations will score better than letting us find them! o A user manual + + +Design Rationale + +We designed our implementation for the different binary search trees with the goal of providing a reusable crate that could be extended to other types of binary search trees that could potentially be self-balancing. We chose to support: + +[List of operations here] + +Some of the innovations: +- include wrapper functions - encapsulating functionality relating to handling and managing various smart pointers in Rust. Talk about accessing parent/child/sibling/etc +- Using traits to extend and implement commonalities between the RBT and AVL +- Implement concept of smart pointers or something +- something about command line interface +- individual implementations provide different thing +- encapsulate/put library together into a crate and explain why did that + +[Explain briefly each of the implemented operations? - how they relate to one another] + +ANSWER FOLLOWING QUESTIONS (maybe combine them with design rationale above?): +What does a red-black tree provide that cannot be accomplished with ordinary binary +search trees? +- Do you need to apply any kind of error handling in your system (e.g., panic macro, +Option, Result, etc..) +- What components do the Red-black tree and AVL tree have in common? Don’t Repeat +Yourself! Never, ever repeat yourself – a fundamental idea in programming. +- How do we construct our design to “allow it to be efficiently and effectively extended”? For example. Could your code be reused to build a 2-3-4 tree or B tree? + +PART 3 + +RED BLACK TREE BENCHMARK RESULTS: +Elapsed time for 10000: 6 ms +Elapsed time for 40000: 31 ms +Elapsed time for 70000: 57 ms +Elapsed time for 100000: 87 ms +Elapsed time for 130000: 121 ms + +AVL TREE BENCHMARK RESULTS: - L8er + +- AVL is probably going to be more efficient because of height rebalancing factor. +- Other test cases should be accommodated including random insertions of varying numbers instead of in-order insertion. Could also consider decreasing numbers for inserting. Also consider deleting operations as a means of measuring efficiency. +- Yes probably good idea to include other data structures as a baseline. BST might be good baseline since it is essentially an RBT/AVL Tree that like doesn't balance itself or whatever we can figure out what to say later. + From c93cdf17dd2fa1e98dbf89c411d1239cfd450d40 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Fri, 28 Feb 2020 16:43:13 -0700 Subject: [PATCH 43/80] found problem yay --- src/avl_tree.rs | 10 +++++----- src/main.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 490560a..f81b805 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -331,10 +331,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn fix_insert_height(&mut self, node: &mut AVLTreeNode) { node.recalc_height(); - - if node.parent().is_some() { - self.fix_insert_height(&mut node.parent()); - } let balance = Self::get_balance(node); let node_val = node.value(); @@ -360,10 +356,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // Right Left Case if balance < -1 && node_val < node.right().value() { - node.set_right(self.rotate(&node.right(), ROTATE_RIGHT)); + node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); self.rotate(node, ROTATE_LEFT); return } + + if node.parent().is_some() { + self.fix_insert_height(&mut node.parent()); + } } // TODO diff --git a/src/main.rs b/src/main.rs index 7bc4673..23a4b76 100644 --- a/src/main.rs +++ b/src/main.rs @@ -117,7 +117,7 @@ fn main() { // } // it_works(); // print_test(); - delete_cases_2_4(); + // delete_cases_2_4(); - // avl_test(); + avl_test(); } From db776ab461e2e8e8df999dd9e4abeb22b548408d Mon Sep 17 00:00:00 2001 From: raysarinas Date: Fri, 28 Feb 2020 22:52:55 -0700 Subject: [PATCH 44/80] add resuable delete code to avl? --- src/avl_tree.rs | 40 ++++++++++++++++++++++++++++++++++++++++ src/red_black_tree.rs | 4 ---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index f81b805..5a24baa 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -420,7 +420,47 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn delete_node(&mut self, value: T) { + let mut node = self.search(value); + if node.is_none() { + return; + } + + if node.left().value().is_some() && node.right().value().is_some() { + let mut larger = node.left(); + + while larger.right().value().is_some() { // larger.left() + larger = larger.right(); // larger.left() + } + + node.set_value(larger.value().unwrap()); + node = larger.clone(); + } + + // set node to null sibling + let mut child = match node.left() { + Some(_) => node.right(), + None => node.left() + }; + + if !node.compare(&self.root) && node.parent().is_some() { + child.set_parent(node.parent()); + if node.compare(&node.parent().left()) { + node.parent().set_left(child.clone()); + } else { + node.parent().set_right(child.clone()); + } + } else if child.is_none() { + // empty tree if child is None + self.root = None; + } else { + // set root to child + self.root = child.clone(); + child.set_parent(None); + } + + // TODO: fixing height for delete here I think and rebalancing? idk + // fix_delete_height() } fn print(&self) { diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index a9db504..cd5560a 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -487,7 +487,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!("DELETE CASE 5 - RIGHT ROTATE"); sibling.left().set_color(NodeColor::Black); self.rotate(&sibling.left(), ROTATE_RIGHT); - // rotate_right(sibling.left()); } } else if node.compare(&node.parent().right()) { @@ -495,7 +494,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!("DELETE CASE 5 - LEFT ROTATE"); sibling.right().set_color(NodeColor::Black); self.rotate(&sibling.left(), ROTATE_LEFT); - // rotate_left(sibling.left()); } } @@ -511,11 +509,9 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb if node.compare(&node.parent().left()) { sibling.right().set_color(NodeColor::Black); self.rotate(&sibling, ROTATE_LEFT); - // rotate_left(sibling); } else { sibling.left().set_color(NodeColor::Black); self.rotate(&sibling, ROTATE_RIGHT); - // rotate_right(sibling); } } From d6cda0bf4965b1ede29fec2c072500a751a3b40a Mon Sep 17 00:00:00 2001 From: raysarinas Date: Fri, 28 Feb 2020 23:15:07 -0700 Subject: [PATCH 45/80] add benchmarks to cli --- src/main.rs | 28 ++++++++++++++++++++++++++-- src/tests.rs | 4 ++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 23a4b76..a053454 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,10 +10,17 @@ use std::io::{stdin, stdout, Write}; static MAIN_MENU: &str = " 1. Red Black Tree 2. AVL Tree -3. Run benchmark tests +3. Run Benchmark Tests 4. Exit "; +static BENCHMARK_MENU: &str = " +BENCHMARK TESTS +1. Red Black Tree Tests +2. AVL Tree Tests +3. Return to main menu +"; + static RBT_MENU: &str = " RED-BLACK TREE 1. Insert a node to the red-black tree @@ -100,6 +107,23 @@ fn rbt() { } } +fn benchmark_tests() { + loop { + println!("{}", BENCHMARK_MENU); + let choice = get_input(">"); + match choice { + 1 => { + benchmark_redblack(); + }, + 2 => { + benchmark_avl(); + }, + 3 => break, + _ => println!("Invalid input!") + } + } +} + fn main() { // loop { // println!("{}", MAIN_MENU); @@ -107,7 +131,7 @@ fn main() { // match choice { // 1 => rbt(), // 2 => avl(), - // 3 => it_works(), + // 3 => benchmark_tests(), // 4 => { // println!("ok bye"); // break; diff --git a/src/tests.rs b/src/tests.rs index 8a7989c..ce71ba1 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -16,7 +16,7 @@ pub fn benchmark_redblack() { for i in 0..tree_size/10 { match tree.contains(i) { - true => { }, + true => { continue; }, false => println!("nope"), } } @@ -37,7 +37,7 @@ pub fn benchmark_avl() { for i in 0..tree_size/10 { match tree.contains(i) { - true => { }, + true => { continue; }, false => println!("nope"), } } From ea85108e8c2776c977a9a8c6ea925020e3d0ba43 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sat, 29 Feb 2020 20:08:33 -0700 Subject: [PATCH 46/80] insert might be done --- src/avl_tree.rs | 139 ++++++++++++++++++++++++++++++++++++++---------- src/tests.rs | 39 +++++++++----- 2 files changed, 139 insertions(+), 39 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 5a24baa..3853554 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -77,19 +77,21 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } fn find_node(&self, value: T) -> AVLTreeNode { - match self { + match self.value() { Some(_) => { - println!("hehe2"); if value == self.value().unwrap() { - println!("hehe2.1"); + println!("inserted values are equal"); self.clone() } else if value < self.value().unwrap() { - println!("hehe2.2"); + println!("going to LEFT"); self.left().find_node(value) - }else { - println!("hehe2.3"); + } else if value > self.value().unwrap() { + println!("trying to find in RIGHT"); self.right().find_node(value) } + else { + None + } }, None => None } @@ -114,6 +116,7 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } fn recalc_height(&mut self) { + println!("enering recalc height. trying to rebalance === {:?}", self.value()); let left = self.left(); let right = self.right(); self.set_height(1 + max(left.height(), right.height())); @@ -316,52 +319,131 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D node.left().set_parent(parent.clone()); } parent.set_right(node.left()); + parent.recalc_height(); node.set_left(parent); } else { if node.right().is_some() { node.right().set_parent(parent.clone()); } parent.set_left(node.right()); + parent.recalc_height(); node.set_right(parent); } + node.recalc_height(); + // parent.recalc_height(); + node } // TODO fn fix_insert_height(&mut self, node: &mut AVLTreeNode) { + println!("entering fix_insert_height"); node.recalc_height(); let balance = Self::get_balance(node); let node_val = node.value(); + println!("value of node = {:?} and balance = {:?}", node_val, balance); + println!("HEIGHT OF NODE = {:?}", node.height()); - // Left Left Case - if balance > 1 && node_val < node.left().value() { - self.rotate(node, ROTATE_RIGHT); - return + if balance > 1 { + // left 2 heavy } - // Right Right Case - if balance < -1 && node_val > node.right().value() { - self.rotate(node, ROTATE_LEFT); - return + if balance < -1 { + // right 2 heavy + } - // Left Right Case - if balance > 1 && node_val > node.left().value() { - node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); - self.rotate(node, ROTATE_RIGHT); - return + // Left Left Case + // if balance > 1 {//&& node_val < node.left().value() { + // self.rotate(&node.left(), ROTATE_RIGHT); + // return + // } + + // Right Right Case + // if balance < -1 {//&& node_val > node.right().value() { + // self.rotate(&node.right(), ROTATE_LEFT); + // return + // } + + // // Left Cases + // if balance > 1 { + // println!("LEFT 2 HEAVY"); + // // LEFT RIGHT + // if node.left().right().height() > node.left().left().height() { + // println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); + // self.rotate(&node.left().right(), ROTATE_LEFT); + // // node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); + // self.rotate(&node.left(), ROTATE_RIGHT); + // self.root.recalc_height(); + // println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // return + // } + // // LEFT LEFT + // else if node.left().right().height() < node.left().left().height() { + // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); + // self.rotate(&node.left(), ROTATE_RIGHT); + // self.root.recalc_height(); + // println!("height is now ====== {:?}", self.root.height()); + // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // return; + // } + // } + + // Left Cases + if balance > 1 { + println!("LEFT 2 HEAVY"); + // LEFT RIGHT + if node.left().right().height() > node.left().left().height() { + println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); + self.rotate(&node.left().right(), ROTATE_LEFT); + // node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); + self.rotate(&node.left(), ROTATE_RIGHT); + self.root.recalc_height(); + println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + return + } + // LEFT LEFT + else if node.left().right().height() < node.left().left().height() { + println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); + self.rotate(&node.left(), ROTATE_RIGHT); + self.root.recalc_height(); + println!("height is now ====== {:?}", self.root.height()); + println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + return; + } } - // Right Left Case - if balance < -1 && node_val < node.right().value() { - node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); - self.rotate(node, ROTATE_LEFT); - return + // RIGHT Cases + if balance < -1 { + println!("LEFT 2 HEAVY"); + // RIGHT LEFT RIGHT + + if node.right().left().height() > node.right().right().height() { + println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); + self.rotate(&node.right().left(), ROTATE_RIGHT); + // node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); + self.rotate(&node.right(), ROTATE_LEFT); + self.root.recalc_height(); + println!("height is now ====== {:?}", self.root.height()); + println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + return + } + // LEFT LEFT + else if node.right().left().height() < node.right().right().height() { + println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); + // self.rotate(&node.left(), ROTATE_RIGHT); + self.rotate(&node.right(), ROTATE_LEFT); + self.root.recalc_height(); + println!("height is now ====== {:?}", self.root.height()); + println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + return; + } } - if node.parent().is_some() { + if node.parent().is_some() && !node.compare(&self.root) { + println!("parent is some"); self.fix_insert_height(&mut node.parent()); } } @@ -376,15 +458,17 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // REGULAR BINARY SEARCH TREE INSERTION let mut new_node = AVLTreeNode::new(value); + let did_find_node = self.search(value).is_some(); + println!("did find node? = {}", did_find_node); if self.is_empty() { self.root = new_node.clone(); return - } + } + else if self.search(value).is_some() { println!("Value already exists!"); return; } - else { let mut curr_node = self.root.clone(); let mut curr_node_parent: AVLTreeNode = None; @@ -415,6 +499,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } // TODO: AVL REBALANCING HERE + println!("GOING REBALANCE INSERT"); self.fix_insert_height(&mut new_node); } diff --git a/src/tests.rs b/src/tests.rs index ce71ba1..4c3b2f2 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -316,26 +316,41 @@ pub fn delete_cases_2_4() { println!("\n==== Start Testing AVLTree Here ====\n"); let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + // let mut vec_in: Vec = vec![5, 70, 35]; // right left //, 8, 98, 60]; // poop on 99];//, 8, 98, 60, 99, 99, 1, 84, 17]; + // let mut vec_in: Vec = vec![5, 3, 1]; // left left + // let mut vec_in: Vec = vec![5, 1, 3]; // left right + // let mut vec_in: Vec = vec![5, 70, 90]; // right right + let mut vec_in: Vec = vec![5, 70, 35, 98, 98, 60, 99, 99, 1, 84, 17];//, 98, 60]; + println!("AVL Tree INIT = {:?}", avl); for &x in vec_in.iter() { println!("inserting {} ...", x); avl.insert_node(x); - println!("size is now = {}", avl.size()); + // println!("size is now = {}", avl.size()); avl.print(); println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); println!(); } - vec_in = vec![17, 84, 99, 5, 1, 60]; - for &x in vec_in.iter() { - println!("deleting {} ...", x); - avl.delete_node(x); - println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); - } + println!("inserting {} ...", 98); + avl.insert_node(98); + // println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + + + + // vec_in = vec![17, 84, 99, 5, 1, 60]; + // for &x in vec_in.iter() { + // println!("deleting {} ...", x); + // avl.delete_node(x); + // println!("size is now = {}", avl.size()); + // avl.print(); + // println!("height = {}", avl.height()); + // println!("leaves = {}", avl.count_leaves()); + // println!(); + // } } \ No newline at end of file From bfa3f37e1314e9674f17e722a1431fd4b7229468 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sat, 29 Feb 2020 23:29:24 -0700 Subject: [PATCH 47/80] add benchmark results --- design_doc_draft.txt | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/design_doc_draft.txt b/design_doc_draft.txt index 0b51f75..6df8008 100644 --- a/design_doc_draft.txt +++ b/design_doc_draft.txt @@ -10,11 +10,19 @@ Design Rationale We designed our implementation for the different binary search trees with the goal of providing a reusable crate that could be extended to other types of binary search trees that could potentially be self-balancing. We chose to support: -[List of operations here] +[Description of operations here] +- inserting +- deleting +- leaf counting (this is the same for both) +- height of a tree +- in-order print traversal +- is empty? Some of the innovations: - include wrapper functions - encapsulating functionality relating to handling and managing various smart pointers in Rust. Talk about accessing parent/child/sibling/etc - Using traits to extend and implement commonalities between the RBT and AVL +- Could talk about how some of the binary search functionality for insertion and deletion were re-used. +- Talk about how we specifically chose to implement a top-down approach for insertion in both types of trees so that we could re-use code. Talk about how bottom-up approach maybe for AVL Tree insertion could improve run-time speed with regards to benchmarking. - Implement concept of smart pointers or something - something about command line interface - individual implementations provide different thing @@ -39,10 +47,40 @@ Elapsed time for 40000: 31 ms Elapsed time for 70000: 57 ms Elapsed time for 100000: 87 ms Elapsed time for 130000: 121 ms +== +Elapsed time for 10000: 6 ms +Elapsed time for 40000: 29 ms +Elapsed time for 70000: 58 ms +Elapsed time for 100000: 86 ms +Elapsed time for 130000: 116 ms +== +Elapsed time for 10000: 6 ms +Elapsed time for 40000: 31 ms +Elapsed time for 70000: 58 ms +Elapsed time for 100000: 88 ms +Elapsed time for 130000: 114 ms -AVL TREE BENCHMARK RESULTS: - L8er +AVL TREE BENCHMARK RESULTS: +Elapsed time for 10000: 8 ms +Elapsed time for 40000: 37 ms +Elapsed time for 70000: 65 ms +Elapsed time for 100000: 101 ms +Elapsed time for 130000: 129 ms +== +Elapsed time for 10000: 7 ms +Elapsed time for 40000: 34 ms +Elapsed time for 70000: 64 ms +Elapsed time for 100000: 98 ms +Elapsed time for 130000: 140 ms +== +Elapsed time for 10000: 7 ms +Elapsed time for 40000: 34 ms +Elapsed time for 70000: 64 ms +Elapsed time for 100000: 98 ms +Elapsed time for 130000: 130 ms - AVL is probably going to be more efficient because of height rebalancing factor. +- AVL apparently not as efficient (likely to due top-bottom implementation) - Other test cases should be accommodated including random insertions of varying numbers instead of in-order insertion. Could also consider decreasing numbers for inserting. Also consider deleting operations as a means of measuring efficiency. - Yes probably good idea to include other data structures as a baseline. BST might be good baseline since it is essentially an RBT/AVL Tree that like doesn't balance itself or whatever we can figure out what to say later. From 1dc4ec4d3b6befc77cd59daa02a436931a911e5b Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 12:28:41 -0700 Subject: [PATCH 48/80] cleanup rbt and fix some bugs --- src/avl_tree.rs | 48 +++++------ src/main.rs | 24 ++++-- src/red_black_tree.rs | 191 ++++++++++++++++++++---------------------- src/tests.rs | 23 +++++ 4 files changed, 154 insertions(+), 132 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 3853554..5ec807e 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -80,13 +80,13 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: match self.value() { Some(_) => { if value == self.value().unwrap() { - println!("inserted values are equal"); + // println!("inserted values are equal"); self.clone() } else if value < self.value().unwrap() { - println!("going to LEFT"); + // println!("going to LEFT"); self.left().find_node(value) } else if value > self.value().unwrap() { - println!("trying to find in RIGHT"); + // println!("trying to find in RIGHT"); self.right().find_node(value) } else { @@ -116,7 +116,7 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } fn recalc_height(&mut self) { - println!("enering recalc height. trying to rebalance === {:?}", self.value()); + // println!("enering recalc height. trying to rebalance === {:?}", self.value()); let left = self.left(); let right = self.right(); self.set_height(1 + max(left.height(), right.height())); @@ -338,13 +338,13 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO fn fix_insert_height(&mut self, node: &mut AVLTreeNode) { - println!("entering fix_insert_height"); + // println!("entering fix_insert_height"); node.recalc_height(); let balance = Self::get_balance(node); let node_val = node.value(); - println!("value of node = {:?} and balance = {:?}", node_val, balance); - println!("HEIGHT OF NODE = {:?}", node.height()); + // println!("value of node = {:?} and balance = {:?}", node_val, balance); + // println!("HEIGHT OF NODE = {:?}", node.height()); if balance > 1 { // left 2 heavy @@ -393,57 +393,57 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // Left Cases if balance > 1 { - println!("LEFT 2 HEAVY"); + // println!("LEFT 2 HEAVY"); // LEFT RIGHT if node.left().right().height() > node.left().left().height() { - println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); + // println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); self.rotate(&node.left().right(), ROTATE_LEFT); // node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); self.rotate(&node.left(), ROTATE_RIGHT); self.root.recalc_height(); - println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return } // LEFT LEFT else if node.left().right().height() < node.left().left().height() { - println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); + // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); self.rotate(&node.left(), ROTATE_RIGHT); self.root.recalc_height(); - println!("height is now ====== {:?}", self.root.height()); - println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // println!("height is now ====== {:?}", self.root.height()); + // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return; } } // RIGHT Cases if balance < -1 { - println!("LEFT 2 HEAVY"); + // println!("LEFT 2 HEAVY"); // RIGHT LEFT RIGHT if node.right().left().height() > node.right().right().height() { - println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); + // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); self.rotate(&node.right().left(), ROTATE_RIGHT); // node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); self.rotate(&node.right(), ROTATE_LEFT); self.root.recalc_height(); - println!("height is now ====== {:?}", self.root.height()); - println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // println!("height is now ====== {:?}", self.root.height()); + // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return } // LEFT LEFT else if node.right().left().height() < node.right().right().height() { - println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); + // println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); // self.rotate(&node.left(), ROTATE_RIGHT); self.rotate(&node.right(), ROTATE_LEFT); self.root.recalc_height(); - println!("height is now ====== {:?}", self.root.height()); - println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); + // println!("height is now ====== {:?}", self.root.height()); + // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return; } } if node.parent().is_some() && !node.compare(&self.root) { - println!("parent is some"); + // println!("parent is some"); self.fix_insert_height(&mut node.parent()); } } @@ -458,8 +458,8 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // REGULAR BINARY SEARCH TREE INSERTION let mut new_node = AVLTreeNode::new(value); - let did_find_node = self.search(value).is_some(); - println!("did find node? = {}", did_find_node); + // let did_find_node = self.search(value).is_some(); + // println!("did find node? = {}", did_find_node); if self.is_empty() { self.root = new_node.clone(); return @@ -499,7 +499,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } // TODO: AVL REBALANCING HERE - println!("GOING REBALANCE INSERT"); + // println!("GOING REBALANCE INSERT"); self.fix_insert_height(&mut new_node); } diff --git a/src/main.rs b/src/main.rs index a053454..0527d7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,15 +83,25 @@ fn rbt() { match choice { 1 => { let value = get_input("Value to insert:"); - rbt.insert_node(value); // TODO: error handling? - println!("Inserted {}", value); + let old_size = rbt.size(); + rbt.insert_node(value); + if old_size < rbt.size() { + println!("Successfully inserted {}", value); + } else { + println!("Error inserting value"); + } }, 2 => { let value = get_input("Value to delete:"); - rbt.delete_node(value); // TODO: error handling? - println!("Deleted {}", value); + let old_size = rbt.size(); + rbt.delete_node(value); + if old_size > rbt.size() { + println!("Successfully deleted {}", value); + } else { + println!("Error deleting value"); + } }, - 3 => println!("{}", rbt.size()), + 3 => println!("{}", rbt.count_leaves()), 4 => println!("{}", rbt.height()), 5 => rbt.print(), 6 => { @@ -142,6 +152,6 @@ fn main() { // it_works(); // print_test(); // delete_cases_2_4(); - - avl_test(); + test_delete_rbt(); + // avl_test(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index cd5560a..6a51de5 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -33,7 +33,8 @@ pub trait NodeTraits { fn node_height(&self) -> usize; fn print_traversal(&self); fn count_leaves(&self) -> usize; - fn is_node_red(node: &TreeNode) -> bool; // TODO: replace comparing colors with this function + fn is_red(&self) -> bool; + fn is_black(&self) -> bool; // getters for node properties and family members fn color(&self) -> NodeColor; @@ -116,7 +117,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb fn print_traversal(&self) { if self.is_some() && self.value().is_some() { self.left().print_traversal(); - if self.color() == NodeColor::Red { + if self.is_red() { print!("<{:?}>", self.value().unwrap()); } else { print!("[{:?}]", self.value().unwrap()); @@ -135,8 +136,12 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn is_node_red(node: &TreeNode) -> bool { - node.color() == NodeColor::Red + fn is_red(&self) -> bool { + self.color() == NodeColor::Red + } + + fn is_black(&self) -> bool { + self.color() == NodeColor::Black } fn color(&self) -> NodeColor { @@ -250,14 +255,21 @@ pub struct RBTree { len: usize } +impl RBTree { + pub fn new() -> RBTree { + RBTree { + root: None, + len: 0 + } + } +} + pub trait RBTreeTraits { - fn new() -> RBTree; fn height(&self) -> usize; fn is_empty(&self) -> bool; fn size(&self) -> usize; fn search(&self, value: T) -> TreeNode; fn rotate(&mut self, node: &TreeNode, direction: bool); - fn insert_case5(&mut self, node: &TreeNode); fn fix_insert_color(&mut self, node: &TreeNode); fn fix_delete_color(&mut self, node: &TreeNode); fn insert_node(&mut self, value: T); @@ -268,13 +280,6 @@ pub trait RBTreeTraits { } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { - fn new() -> RBTree { - RBTree { - root: None, - len: 0 - } - } - // TODO ask miller if nil nodes are included fn height(&self) -> usize { self.root.node_height() @@ -338,51 +343,50 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - fn insert_case5(&mut self, node: &TreeNode) { - let parent = node.parent().clone(); - let grandparent = node.grandparent().clone(); - - if node.compare(&parent.left()) { - self.rotate(&parent, ROTATE_RIGHT); - } else { - self.rotate(&parent, ROTATE_LEFT); - } - - parent.set_color(NodeColor::Black); - grandparent.set_color(NodeColor::Red); - } - fn fix_insert_color(&mut self, node: &TreeNode) { - let parent = node.parent().clone(); - let uncle = node.uncle().clone(); - let grandparent = node.grandparent().clone(); - - // case 1 + // CASE 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); - // case 2 - } else if parent.color() == NodeColor::Black { return; - // case 3 - } else if uncle.is_some() && uncle.color() == NodeColor::Red { + } + + // CASE 2 + let parent = node.parent().clone(); + if parent.is_black() { + return; + } + + // CASE 3 + let uncle = node.uncle().clone(); + let grandparent = node.grandparent().clone(); + if uncle.is_some() && uncle.is_red() { parent.set_color(NodeColor::Black); uncle.set_color(NodeColor::Black); grandparent.set_color(NodeColor::Red); self.fix_insert_color(&grandparent); - // case 4 - } else if uncle.color() == NodeColor::Black { // uncle can be a nil node - let mut node = node.clone(); - - if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { - self.rotate(&node, ROTATE_LEFT); - node = node.left(); - } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { - self.rotate(&node, ROTATE_RIGHT); - node = node.right(); - } + return; + } + + // CASE 4 + let mut node = node.clone(); + if node.compare(&parent.right()) && parent.compare(&grandparent.left()) { + self.rotate(&node, ROTATE_LEFT); + node = node.left(); + } else if node.compare(&parent.left()) && parent.compare(&grandparent.right()) { + self.rotate(&node, ROTATE_RIGHT); + node = node.right(); + } - self.insert_case5(&node); + // CASE 5 + let parent = node.parent().clone(); + let grandparent = node.grandparent().clone(); + if node.compare(&parent.left()) { + self.rotate(&parent, ROTATE_RIGHT); + } else { + self.rotate(&parent, ROTATE_LEFT); } + parent.set_color(NodeColor::Black); + grandparent.set_color(NodeColor::Red); } fn insert_node(&mut self, value: T) { @@ -429,83 +433,70 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn fix_delete_color(&mut self, node: &TreeNode) { - // case 1: node is root so done (it’s already black) + // CASE 1: node is root so done (it’s already black) if node.compare(&self.root) { + println!("CASE 1"); return; } let mut sibling = node.sibling(); - // Case 2, sibling of node is red: - // Set parent’s color to red, and sibling’s color to black - // Rotate left/right on sibling if node is a lChild/rChild - // Update sibling to node’s new sibling - if node.parent().is_some() { - println!("DELETE CASE 2"); - // actually start case 2 here: - if sibling.color() == NodeColor::Red { - - sibling.parent().set_color(NodeColor::Red); - sibling.set_color(NodeColor::Black); - - if node.compare(&node.parent().left()) { - self.rotate(&sibling, ROTATE_LEFT); - } else { - self.rotate(&sibling, ROTATE_RIGHT); - } - - // update sibling after rotating - sibling = node.sibling(); + // CASE 2 + if sibling.is_red() { + println!("CASE 2"); + sibling.parent().set_color(NodeColor::Red); + sibling.set_color(NodeColor::Black); + if node.compare(&node.parent().left()) { + self.rotate(&sibling, ROTATE_LEFT); + } else { + self.rotate(&sibling, ROTATE_RIGHT); } + + // update sibling after rotating + sibling = node.sibling(); } // CASE 3 - if node.parent().color() == NodeColor::Black && sibling.color() == NodeColor::Black { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { - println!("DELETE CASE 3"); + if node.parent().is_black() && sibling.is_black() && + sibling.left().is_black() && sibling.right().is_black() { + println!("CASE 3"); sibling.set_color(NodeColor::Red); self.fix_delete_color(&node.parent()); return; - } } + // CASE 4 - if node.parent().color() == NodeColor::Red && sibling.color() == NodeColor::Black { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Black { - println!("DELETE CASE 4"); + if node.parent().is_red() && sibling.is_black() && + sibling.left().is_black() && sibling.right().is_black() { + println!("CASE 4"); sibling.set_color(NodeColor::Red); node.parent().set_color(NodeColor::Black); return; - } } // CASE 5 - if sibling.color() == NodeColor::Black { + if sibling.is_black() { + println!("CASE 5"); sibling.set_color(NodeColor::Red); - if node.compare(&node.parent().left()) { - if sibling.left().color() == NodeColor::Red && sibling.right().color() == NodeColor::Black { - println!("DELETE CASE 5 - RIGHT ROTATE"); + if node.compare(&node.parent().left()) && + sibling.left().is_red() && sibling.right().is_black() { sibling.left().set_color(NodeColor::Black); self.rotate(&sibling.left(), ROTATE_RIGHT); - } + } else if node.compare(&node.parent().right()) && + sibling.left().is_black() && sibling.right().is_red() { + sibling.right().set_color(NodeColor::Black); + self.rotate(&sibling.left(), ROTATE_LEFT); } - else if node.compare(&node.parent().right()) { - if sibling.left().color() == NodeColor::Black && sibling.right().color() == NodeColor::Red { - println!("DELETE CASE 5 - LEFT ROTATE"); - sibling.right().set_color(NodeColor::Black); - self.rotate(&sibling.left(), ROTATE_LEFT); - } - } - - // update sibling - sibling = node.sibling(); + + // update sibling + sibling = node.sibling(); } // CASE 6 - println!("DELETE CASE 6"); sibling.set_color(node.parent().color()); node.parent().set_color(NodeColor::Black); - + println!("CASE 6"); if node.compare(&node.parent().left()) { sibling.right().set_color(NodeColor::Black); self.rotate(&sibling, ROTATE_LEFT); @@ -513,13 +504,13 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb sibling.left().set_color(NodeColor::Black); self.rotate(&sibling, ROTATE_RIGHT); } - } fn delete_node(&mut self, value: T) { let mut node = self.search(value); if node.is_none() { + println!("Node does not exist!"); return; } @@ -536,8 +527,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // set node to null sibling let mut child = match node.left() { - Some(_) => node.right(), - None => node.left() + Some(_) => node.left(), + None => node.right() }; if !node.compare(&self.root) && node.parent().is_some() { @@ -556,12 +547,10 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb child.set_parent(None); } - if node.color() == NodeColor::Black { - if child.color() == NodeColor::Red { - println!("dont need to fix color"); + if node.is_black() { + if child.is_red() { child.set_color(NodeColor::Black); } else { - println!("Fixing Color"); self.fix_delete_color(&child); } } diff --git a/src/tests.rs b/src/tests.rs index 4c3b2f2..a5a6a13 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -249,6 +249,29 @@ pub fn it_works() { +} + +pub fn test_delete_rbt() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + for x in 1..=10 { + rbt.insert_node(x); + println!("inserting ... {}", x); + } + + rbt.delete_node(6); + // rbt.print(); + rbt.delete_node(4); + // rbt.print(); + rbt.delete_node(2); + // rbt.print(); + rbt.delete_node(8); + rbt.delete_node(9); + rbt.delete_node(7); + rbt.delete_node(3); + rbt.delete_node(1); + rbt.delete_node(5); + // rbt.print(); } pub fn delete_cases_1_3_5_6() { From f70a2088e7c038cf5716183275eba1892149aeb4 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 12:42:30 -0700 Subject: [PATCH 49/80] delete should be good now --- src/red_black_tree.rs | 9 ++------- src/tests.rs | 9 ++++++++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 6a51de5..8058a2b 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -435,7 +435,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb fn fix_delete_color(&mut self, node: &TreeNode) { // CASE 1: node is root so done (it’s already black) if node.compare(&self.root) { - println!("CASE 1"); return; } @@ -443,7 +442,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 2 if sibling.is_red() { - println!("CASE 2"); sibling.parent().set_color(NodeColor::Red); sibling.set_color(NodeColor::Black); @@ -460,7 +458,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 3 if node.parent().is_black() && sibling.is_black() && sibling.left().is_black() && sibling.right().is_black() { - println!("CASE 3"); sibling.set_color(NodeColor::Red); self.fix_delete_color(&node.parent()); return; @@ -469,7 +466,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 4 if node.parent().is_red() && sibling.is_black() && sibling.left().is_black() && sibling.right().is_black() { - println!("CASE 4"); sibling.set_color(NodeColor::Red); node.parent().set_color(NodeColor::Black); return; @@ -477,7 +473,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 5 if sibling.is_black() { - println!("CASE 5"); sibling.set_color(NodeColor::Red); if node.compare(&node.parent().left()) && sibling.left().is_red() && sibling.right().is_black() { @@ -496,7 +491,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb // CASE 6 sibling.set_color(node.parent().color()); node.parent().set_color(NodeColor::Black); - println!("CASE 6"); if node.compare(&node.parent().left()) { sibling.right().set_color(NodeColor::Black); self.rotate(&sibling, ROTATE_LEFT); @@ -526,7 +520,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } // set node to null sibling - let mut child = match node.left() { + let mut child = match node.left().value() { Some(_) => node.left(), None => node.right() }; @@ -541,6 +535,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } else if child.is_none() { // empty tree if child is None self.root = None; + return; } else { // set root to child self.root = child.clone(); diff --git a/src/tests.rs b/src/tests.rs index a5a6a13..f370fed 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -259,6 +259,11 @@ pub fn test_delete_rbt() { println!("inserting ... {}", x); } + assert!(rbt.is_empty() == false); + rbt.print(); + + println!("deleting everything .."); + rbt.delete_node(6); // rbt.print(); rbt.delete_node(4); @@ -271,7 +276,9 @@ pub fn test_delete_rbt() { rbt.delete_node(3); rbt.delete_node(1); rbt.delete_node(5); - // rbt.print(); + rbt.delete_node(10); + assert!(rbt.is_empty() == true); + rbt.print(); } pub fn delete_cases_1_3_5_6() { From 08c95c57d264313f9be33c22159e85697d9f8183 Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Sun, 1 Mar 2020 13:45:38 -0700 Subject: [PATCH 50/80] delete maybe done and avl menu --- src/avl_tree.rs | 1 + src/main.rs | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 5ec807e..264ddf8 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -546,6 +546,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // TODO: fixing height for delete here I think and rebalancing? idk // fix_delete_height() + self.fix_insert_height(&mut node); } fn print(&self) { diff --git a/src/main.rs b/src/main.rs index 0527d7f..6cdb1e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod red_black_tree; mod tests; use red_black_tree::*; +use avl_tree::*; use tests::*; use std::io::{stdin, stdout, Write}; @@ -58,16 +59,29 @@ fn get_input(prompt: &str) -> u32 { } fn avl() { + let mut avl: AVLTree = AVLTree::new(); loop { println!("{}", AVL_MENU); let choice = get_input(">"); match choice { - 1 => {}, - 2 => {}, - 3 => {}, - 4 => {}, - 5 => {}, - 6 => {}, + 1 => { + let value = get_input("Value to insert:"); + avl.insert_node(value); + }, + 2 => { + let value = get_input("Value to delete:"); + avl.delete_node(value); + }, + 3 => println!("{}", avl.count_leaves()), + 4 => println!("{}", avl.height()), + 5 => avl.print(), + 6 => { + if avl.is_empty() { + println!("Tree is empty."); + } else { + println!("nah tree is full of leaves"); + } + }, 7 => break, _ => println!("Invalid input!") } From 01dbcea99a231a8e29276d3f5e1a4d51c32a43de Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 13:52:10 -0700 Subject: [PATCH 51/80] fixed height and count_leaves --- src/main.rs | 30 +++++++++++++++--------------- src/red_black_tree.rs | 7 ++++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0527d7f..a150037 100644 --- a/src/main.rs +++ b/src/main.rs @@ -135,23 +135,23 @@ fn benchmark_tests() { } fn main() { - // loop { - // println!("{}", MAIN_MENU); - // let choice = get_input(">"); - // match choice { - // 1 => rbt(), - // 2 => avl(), - // 3 => benchmark_tests(), - // 4 => { - // println!("ok bye"); - // break; - // }, - // _ => println!("Invalid input!") - // } - // } + loop { + println!("{}", MAIN_MENU); + let choice = get_input(">"); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => benchmark_tests(), + 4 => { + println!("ok bye"); + break; + }, + _ => println!("Invalid input!") + } + } // it_works(); // print_test(); // delete_cases_2_4(); - test_delete_rbt(); + // test_delete_rbt(); // avl_test(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 8058a2b..78f56a0 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -99,7 +99,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } fn node_height(&self) -> usize { - match self { + match self.value() { Some(_) => { let left_height = self.left().node_height(); let right_height = self.right().node_height(); @@ -127,9 +127,9 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } fn count_leaves(&self) -> usize { - if self.is_none() { + if self.value().is_none() { 0 - } else if self.left().is_none() && self.right().is_none() { + } else if self.left().value().is_none() && self.right().value().is_none() { 1 } else { self.left().count_leaves() + self.right().count_leaves() @@ -535,6 +535,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } else if child.is_none() { // empty tree if child is None self.root = None; + self.len -= 1; return; } else { // set root to child From cf3f2f48183fbc77a016135c69a71adef99d265c Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 1 Mar 2020 14:16:23 -0700 Subject: [PATCH 52/80] clean up + fix count_leaves --- src/avl_tree.rs | 133 +++++------------------------------------------- src/main.rs | 30 +++++------ 2 files changed, 27 insertions(+), 136 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 264ddf8..8c4fbd6 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -106,9 +106,9 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } fn count_leaves(&self) -> usize { - if self.is_none() { + if self.value().is_none() { 0 - } else if self.left().is_none() && self.right().is_none() { + } else if self.left().value().is_none() && self.right().value().is_none() { 1 } else { self.left().count_leaves() + self.right().count_leaves() @@ -240,9 +240,8 @@ pub trait AVLTreeTraits { fn size(&self) -> usize; fn search(&self, value: T) -> AVLTreeNode; fn get_balance(node: &AVLTreeNode) -> isize; - fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode; - fn fix_insert_height(&mut self, node: &mut AVLTreeNode); - fn fix_delete_height(&mut self, node: &AVLTreeNode); + fn rotate(&mut self, node: &AVLTreeNode, direction: bool); + fn rebalance(&mut self, node: &mut AVLTreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); @@ -282,21 +281,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } } - // TODO - fn rotate(&mut self, node: &AVLTreeNode, direction: bool) -> AVLTreeNode { - // let mut v = node.right(); - // if direction == ROTATE_RIGHT { - // v = node.left(); - // } - - // v.set_parent(node.parent()); - - // if direction == ROTATE_LEFT { - // node.set_right(v.left()); - // match node.right() { - // Some(tree_node) => node.right().set_parent(*node), - // } - // } + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); @@ -331,67 +316,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } node.recalc_height(); - // parent.recalc_height(); - - node } // TODO - fn fix_insert_height(&mut self, node: &mut AVLTreeNode) { - // println!("entering fix_insert_height"); + fn rebalance(&mut self, node: &mut AVLTreeNode) { node.recalc_height(); - let balance = Self::get_balance(node); - let node_val = node.value(); - // println!("value of node = {:?} and balance = {:?}", node_val, balance); - // println!("HEIGHT OF NODE = {:?}", node.height()); - if balance > 1 { - // left 2 heavy - } - - if balance < -1 { - // right 2 heavy - - } - - // Left Left Case - // if balance > 1 {//&& node_val < node.left().value() { - // self.rotate(&node.left(), ROTATE_RIGHT); - // return - // } - - // Right Right Case - // if balance < -1 {//&& node_val > node.right().value() { - // self.rotate(&node.right(), ROTATE_LEFT); - // return - // } - - // // Left Cases - // if balance > 1 { - // println!("LEFT 2 HEAVY"); - // // LEFT RIGHT - // if node.left().right().height() > node.left().left().height() { - // println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); - // self.rotate(&node.left().right(), ROTATE_LEFT); - // // node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); - // self.rotate(&node.left(), ROTATE_RIGHT); - // self.root.recalc_height(); - // println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); - // return - // } - // // LEFT LEFT - // else if node.left().right().height() < node.left().left().height() { - // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); - // self.rotate(&node.left(), ROTATE_RIGHT); - // self.root.recalc_height(); - // println!("height is now ====== {:?}", self.root.height()); - // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); - // return; - // } - // } - - // Left Cases + // Left Cases if balance > 1 { // println!("LEFT 2 HEAVY"); // LEFT RIGHT @@ -419,7 +351,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D if balance < -1 { // println!("LEFT 2 HEAVY"); // RIGHT LEFT RIGHT - if node.right().left().height() > node.right().right().height() { // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); self.rotate(&node.right().left(), ROTATE_RIGHT); @@ -443,23 +374,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } if node.parent().is_some() && !node.compare(&self.root) { - // println!("parent is some"); - self.fix_insert_height(&mut node.parent()); + self.rebalance(&mut node.parent()); } } - // TODO - fn fix_delete_height(&mut self, node: &AVLTreeNode) { - - } - - // TODO fn insert_node(&mut self, value: T) { - // REGULAR BINARY SEARCH TREE INSERTION let mut new_node = AVLTreeNode::new(value); - // let did_find_node = self.search(value).is_some(); - // println!("did find node? = {}", did_find_node); + if self.is_empty() { self.root = new_node.clone(); return @@ -498,12 +420,9 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } } - // TODO: AVL REBALANCING HERE - // println!("GOING REBALANCE INSERT"); - self.fix_insert_height(&mut new_node); + self.rebalance(&mut new_node); } - // TODO fn delete_node(&mut self, value: T) { let mut node = self.search(value); @@ -544,9 +463,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D child.set_parent(None); } - // TODO: fixing height for delete here I think and rebalancing? idk - // fix_delete_height() - self.fix_insert_height(&mut node); + self.rebalance(&mut node); } fn print(&self) { @@ -569,30 +486,4 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D None => false } } -} -// fn rotate_left(&mut self) { -// if self.right.is_none() { -// return -// } - -// let right_child = self.right.as_mut().unwrap().borrow(); -// let right_left = right_child.left.take(); -// let right_right = right_child.right.take(); - -// // Replace current right child with right grandchild -// let mut new_left_tree = replace(&mut self.right, right_right); -// swap(&mut self.value, &mut new_left_tree.as_mut().unwrap().borrow().value); - -// let left_tree = self.left.take(); -// let new_left_node = new_left_tree.as_mut().unwrap().borrow(); - -// new_left_node.right = right_left; -// new_left_node.left = left_tree; -// self.left = new_left_tree; - -// if let Some(node) = self.left.as_mut() { -// self.left.as_mut().unwrap().borrow().recalc_height(); -// } - -// self.recalc_height(); -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e1cbcab..eb90161 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,23 +149,23 @@ fn benchmark_tests() { } fn main() { - loop { - println!("{}", MAIN_MENU); - let choice = get_input(">"); - match choice { - 1 => rbt(), - 2 => avl(), - 3 => benchmark_tests(), - 4 => { - println!("ok bye"); - break; - }, - _ => println!("Invalid input!") - } - } + // loop { + // println!("{}", MAIN_MENU); + // let choice = get_input(">"); + // match choice { + // 1 => rbt(), + // 2 => avl(), + // 3 => benchmark_tests(), + // 4 => { + // println!("ok bye"); + // break; + // }, + // _ => println!("Invalid input!") + // } + // } // it_works(); // print_test(); // delete_cases_2_4(); // test_delete_rbt(); - // avl_test(); + avl_test(); } From 2cc0e034a44ddcd89f7f6abd65555400cb6e2432 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 1 Mar 2020 15:25:37 -0700 Subject: [PATCH 53/80] fix stack overflow i guess --- src/avl_tree.rs | 19 +++++++++++-------- src/main.rs | 3 ++- src/tests.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 8c4fbd6..7e5f83a 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::rc::Rc; -use std::mem::{replace, swap}; use std::cmp::max; static ROTATE_LEFT: bool = true; @@ -109,14 +108,15 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: if self.value().is_none() { 0 } else if self.left().value().is_none() && self.right().value().is_none() { + println!("leaf is = {:?} with parent = {:?}", self.value(), self.parent().value()); 1 } else { + println!("PARENT = {:?} WITH NODE ON LEFT = {:?} ===== NODE ON RIGHT = {:?}", self.value(), self.left().value(), self.right().value()); self.left().count_leaves() + self.right().count_leaves() } } fn recalc_height(&mut self) { - // println!("enering recalc height. trying to rebalance === {:?}", self.value()); let left = self.left(); let right = self.right(); self.set_height(1 + max(left.height(), right.height())); @@ -337,7 +337,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D return } // LEFT LEFT - else if node.left().right().height() < node.left().left().height() { + else if node.left().right().height() <= node.left().left().height() { // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); self.rotate(&node.left(), ROTATE_RIGHT); self.root.recalc_height(); @@ -349,10 +349,10 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // RIGHT Cases if balance < -1 { - // println!("LEFT 2 HEAVY"); + println!("RIGHT 2 HEAVY"); // RIGHT LEFT RIGHT if node.right().left().height() > node.right().right().height() { - // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); + println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); self.rotate(&node.right().left(), ROTATE_RIGHT); // node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); self.rotate(&node.right(), ROTATE_LEFT); @@ -361,9 +361,9 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return } - // LEFT LEFT - else if node.right().left().height() < node.right().right().height() { - // println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); + // RIGHT RIGHT + else if node.right().left().height() <= node.right().right().height() { + println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); // self.rotate(&node.left(), ROTATE_RIGHT); self.rotate(&node.right(), ROTATE_LEFT); self.root.recalc_height(); @@ -371,6 +371,9 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return; } + else { + println!("DIDNT GET TO ANYTHING"); + } } if node.parent().is_some() && !node.compare(&self.root) { diff --git a/src/main.rs b/src/main.rs index eb90161..e9353fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -167,5 +167,6 @@ fn main() { // print_test(); // delete_cases_2_4(); // test_delete_rbt(); - avl_test(); + // avl_test(); + delete_avl(); } diff --git a/src/tests.rs b/src/tests.rs index f370fed..51d6089 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -383,4 +383,51 @@ pub fn delete_cases_2_4() { // println!("leaves = {}", avl.count_leaves()); // println!(); // } - } \ No newline at end of file + } + + pub fn delete_avl() { + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + + for x in 1..=10 { + avl.insert_node(x); + println!("inserting ... {}", x); + } + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!("=========================="); + println!("deleting {} ...", 4); + avl.delete_node(4); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 8); + avl.delete_node(8); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 1); + avl.delete_node(1); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 3); + avl.delete_node(3); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 2); + avl.delete_node(2); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + + + + println!(); + +} \ No newline at end of file From 70ec33ce2ce6563569858390cf2c1cacf371a46c Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 16:07:51 -0700 Subject: [PATCH 54/80] child thing --- src/avl_tree.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 7e5f83a..624f843 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -445,9 +445,9 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } // set node to null sibling - let mut child = match node.left() { - Some(_) => node.right(), - None => node.left() + let mut child = match node.left().value() { + Some(_) => node.left(), + None => node.right() }; if !node.compare(&self.root) && node.parent().is_some() { From b3d49c2e7621ea66f478490d3946a6006ea9fe7b Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Sun, 1 Mar 2020 22:08:07 -0700 Subject: [PATCH 55/80] maybe avl delete i guess --- src/avl_tree.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 624f843..758ed1d 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -429,6 +429,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn delete_node(&mut self, value: T) { let mut node = self.search(value); + let mut test = node.left(); + if node.left().value().is_none() && node.right().value().is_none() { + test = node.parent(); + } + else if node.left().value().is_none() && node.right().value().is_some() { + test = node.right(); + } + if node.is_none() { return; } @@ -466,7 +474,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D child.set_parent(None); } - self.rebalance(&mut node); + self.rebalance(&mut test); } fn print(&self) { From abb1ca486021f80d6b69cf7f77e3eed964d2ce52 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 1 Mar 2020 22:24:01 -0700 Subject: [PATCH 56/80] no more overflow --- src/avl_tree.rs | 1 + src/tests.rs | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 758ed1d..f0a9aa8 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -468,6 +468,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } else if child.is_none() { // empty tree if child is None self.root = None; + return; } else { // set root to child self.root = child.clone(); diff --git a/src/tests.rs b/src/tests.rs index 51d6089..6618f8a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -384,7 +384,6 @@ pub fn delete_cases_2_4() { // println!(); // } } - pub fn delete_avl() { let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); @@ -402,14 +401,20 @@ pub fn delete_cases_2_4() { println!("leaves = {}", avl.count_leaves()); avl.print(); println!("=========================="); + println!("deleting {} ...", 5); + avl.delete_node(5); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); println!("deleting {} ...", 8); avl.delete_node(8); println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); avl.print(); println!("=========================="); - println!("deleting {} ...", 1); - avl.delete_node(1); + println!("deleting {} ...", 7); + avl.delete_node(7); println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); avl.print(); @@ -425,8 +430,30 @@ pub fn delete_cases_2_4() { println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); avl.print(); - - + println!("=========================="); + println!("deleting {} ...", 1); + avl.delete_node(1); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 9); + avl.delete_node(9); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 6); + avl.delete_node(6); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + println!("deleting {} ...", 10); + avl.delete_node(10); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); println!(); From 69a6190120ac40bb4db712df9284a02836c82f8e Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 1 Mar 2020 22:34:42 -0700 Subject: [PATCH 57/80] remove comments --- src/avl_tree.rs | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index f0a9aa8..2aa6171 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -79,13 +79,10 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: match self.value() { Some(_) => { if value == self.value().unwrap() { - // println!("inserted values are equal"); self.clone() } else if value < self.value().unwrap() { - // println!("going to LEFT"); self.left().find_node(value) } else if value > self.value().unwrap() { - // println!("trying to find in RIGHT"); self.right().find_node(value) } else { @@ -108,10 +105,8 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: if self.value().is_none() { 0 } else if self.left().value().is_none() && self.right().value().is_none() { - println!("leaf is = {:?} with parent = {:?}", self.value(), self.parent().value()); 1 } else { - println!("PARENT = {:?} WITH NODE ON LEFT = {:?} ===== NODE ON RIGHT = {:?}", self.value(), self.left().value(), self.right().value()); self.left().count_leaves() + self.right().count_leaves() } } @@ -325,24 +320,17 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // Left Cases if balance > 1 { - // println!("LEFT 2 HEAVY"); // LEFT RIGHT if node.left().right().height() > node.left().left().height() { - // println!(">>>>>>>>>>>>>>>> LEFT RIGHT CASE"); self.rotate(&node.left().right(), ROTATE_LEFT); - // node.set_left(self.rotate(&node.left(), ROTATE_LEFT)); self.rotate(&node.left(), ROTATE_RIGHT); self.root.recalc_height(); - // println!("LEAVES left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return } // LEFT LEFT else if node.left().right().height() <= node.left().left().height() { - // println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LEFTLEFT"); self.rotate(&node.left(), ROTATE_RIGHT); self.root.recalc_height(); - // println!("height is now ====== {:?}", self.root.height()); - // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return; } } @@ -350,30 +338,19 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // RIGHT Cases if balance < -1 { println!("RIGHT 2 HEAVY"); - // RIGHT LEFT RIGHT + // RIGHT LEFT if node.right().left().height() > node.right().right().height() { - println!(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>RIGHT LEFT"); self.rotate(&node.right().left(), ROTATE_RIGHT); - // node.set_right(self.rotate(&node.right().left(), ROTATE_RIGHT)); self.rotate(&node.right(), ROTATE_LEFT); self.root.recalc_height(); - // println!("height is now ====== {:?}", self.root.height()); - // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); - return + return; } // RIGHT RIGHT else if node.right().left().height() <= node.right().right().height() { - println!("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%RIGHT RIGHT"); - // self.rotate(&node.left(), ROTATE_RIGHT); self.rotate(&node.right(), ROTATE_LEFT); self.root.recalc_height(); - // println!("height is now ====== {:?}", self.root.height()); - // println!("left is {:?} and right is {:?}", self.root.left().height(), self.root.right().height()); return; } - else { - println!("DIDNT GET TO ANYTHING"); - } } if node.parent().is_some() && !node.compare(&self.root) { @@ -398,6 +375,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D let mut curr_node = self.root.clone(); let mut curr_node_parent: AVLTreeNode = None; let mut is_left_child = true; + // find empty node while curr_node.value().is_some() { curr_node_parent = curr_node.clone(); From 76a96ecf8a89fdb1fec0dc4764d2b46d78a85244 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 22:54:09 -0700 Subject: [PATCH 58/80] add size and hopefully avl done --- src/avl_tree.rs | 17 ++++++++--------- src/main.rs | 42 +++++++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 2aa6171..94874a7 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -5,7 +5,6 @@ use std::cmp::max; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; - pub type AVLTreeNode = Option>>>; #[derive(Clone, Debug, PartialEq)] @@ -43,8 +42,6 @@ pub trait NodeTraits { fn set_parent(&mut self, parent: AVLTreeNode); fn set_left(&mut self, left: AVLTreeNode); fn set_right(&mut self, right: AVLTreeNode); - - } impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { @@ -219,13 +216,13 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: }))) } } - } /******************** AVL Tree Helpers ********************/ #[derive(Clone, Debug, PartialEq)] pub struct AVLTree { root: AVLTreeNode, + len: usize } pub trait AVLTreeTraits { @@ -248,6 +245,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn new() -> AVLTree { AVLTree { root: None, + len: 0 } } @@ -259,9 +257,8 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D self.root.is_none() } - // DO WE NEED SIZE? fn size(&self) -> usize { - 1 + self.len } fn search(&self, value: T) -> AVLTreeNode { @@ -277,7 +274,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { - let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); let mut node = node.clone(); @@ -313,7 +309,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D node.recalc_height(); } - // TODO fn rebalance(&mut self, node: &mut AVLTreeNode) { node.recalc_height(); let balance = Self::get_balance(node); @@ -337,7 +332,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D // RIGHT Cases if balance < -1 { - println!("RIGHT 2 HEAVY"); // RIGHT LEFT if node.right().left().height() > node.right().right().height() { self.rotate(&node.right().left(), ROTATE_RIGHT); @@ -364,6 +358,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D if self.is_empty() { self.root = new_node.clone(); + self.len += 1; return } @@ -402,6 +397,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } self.rebalance(&mut new_node); + self.len += 1; } fn delete_node(&mut self, value: T) { @@ -416,6 +412,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } if node.is_none() { + println!("Node does not exist!"); return; } @@ -446,6 +443,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } else if child.is_none() { // empty tree if child is None self.root = None; + self.len -= 1; return; } else { // set root to child @@ -454,6 +452,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } self.rebalance(&mut test); + self.len -= 1; } fn print(&self) { diff --git a/src/main.rs b/src/main.rs index e9353fa..ee737bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,11 +66,23 @@ fn avl() { match choice { 1 => { let value = get_input("Value to insert:"); + let old_size = avl.size(); avl.insert_node(value); + if old_size < avl.size() { + println!("Successfully inserted {}", value); + } else { + println!("Error inserting value"); + } }, 2 => { let value = get_input("Value to delete:"); + let old_size = avl.size(); avl.delete_node(value); + if old_size > avl.size() { + println!("Successfully deleted {}", value); + } else { + println!("Error deleting value"); + } }, 3 => println!("{}", avl.count_leaves()), 4 => println!("{}", avl.height()), @@ -149,24 +161,24 @@ fn benchmark_tests() { } fn main() { - // loop { - // println!("{}", MAIN_MENU); - // let choice = get_input(">"); - // match choice { - // 1 => rbt(), - // 2 => avl(), - // 3 => benchmark_tests(), - // 4 => { - // println!("ok bye"); - // break; - // }, - // _ => println!("Invalid input!") - // } - // } + loop { + println!("{}", MAIN_MENU); + let choice = get_input(">"); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => benchmark_tests(), + 4 => { + println!("ok bye"); + break; + }, + _ => println!("Invalid input!") + } + } // it_works(); // print_test(); // delete_cases_2_4(); // test_delete_rbt(); // avl_test(); - delete_avl(); + // delete_avl(); } From 25532bbdee277f99b8d523be9c435d9068d4128e Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 23:04:52 -0700 Subject: [PATCH 59/80] moved stuff around --- src/avl_tree.rs | 67 ++++++++++++++++++++++--------------------- src/red_black_tree.rs | 12 ++++---- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 94874a7..00e5de5 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -25,6 +25,7 @@ pub trait NodeTraits { fn print_traversal(&self); fn count_leaves(&self) -> usize; fn recalc_height(&mut self); // AVL + fn get_balance(&self) -> isize; // AVL // getters for node properties and family members fn height(&self) -> isize; // AVL @@ -121,6 +122,14 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } + fn get_balance(&self) -> isize { + if self.is_none() { + 0 + } else { + self.left().height() - self.right().height() + } + } + fn value(&self) -> Option { match self { Some(tree_node) => tree_node.borrow().value, @@ -225,30 +234,30 @@ pub struct AVLTree { len: usize } +impl AVLTree { + pub fn new() -> AVLTree { + AVLTree { + root: None, + len: 0 + } + } +} + pub trait AVLTreeTraits { - fn new() -> AVLTree; fn height(&self) -> usize; fn is_empty(&self) -> bool; fn size(&self) -> usize; fn search(&self, value: T) -> AVLTreeNode; - fn get_balance(node: &AVLTreeNode) -> isize; + fn contains(&self, value: T) -> bool; + fn count_leaves(&self) -> usize; fn rotate(&mut self, node: &AVLTreeNode, direction: bool); fn rebalance(&mut self, node: &mut AVLTreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn count_leaves(&self) -> usize; - fn contains(&self, value: T) -> bool; } impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { - fn new() -> AVLTree { - AVLTree { - root: None, - len: 0 - } - } - fn height(&self) -> usize { self.root.height() as usize } @@ -265,14 +274,17 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D self.root.find_node(value) } - fn get_balance(node: &AVLTreeNode) -> isize { - if node.is_none() { - 0 - } else { - node.left().height() - node.right().height() + fn contains(&self, value: T) -> bool { + match self.search(value) { + Some(_) => true, + None => false } } + fn count_leaves(&self) -> usize { + self.root.count_leaves() + } + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); @@ -311,7 +323,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn rebalance(&mut self, node: &mut AVLTreeNode) { node.recalc_height(); - let balance = Self::get_balance(node); + let balance = node.get_balance(); // Left Cases if balance > 1 { @@ -403,6 +415,11 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn delete_node(&mut self, value: T) { let mut node = self.search(value); + if node.is_none() { + println!("Node does not exist!"); + return; + } + let mut test = node.left(); if node.left().value().is_none() && node.right().value().is_none() { test = node.parent(); @@ -411,11 +428,6 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D test = node.right(); } - if node.is_none() { - println!("Node does not exist!"); - return; - } - if node.left().value().is_some() && node.right().value().is_some() { let mut larger = node.left(); @@ -464,15 +476,4 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D println!(); } } - - fn count_leaves(&self) -> usize { - self.root.count_leaves() - } - - fn contains(&self, value: T) -> bool { - match self.search(value) { - Some(_) => true, - None => false - } - } } \ No newline at end of file diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 78f56a0..5c3a95d 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -269,14 +269,14 @@ pub trait RBTreeTraits { fn is_empty(&self) -> bool; fn size(&self) -> usize; fn search(&self, value: T) -> TreeNode; + fn contains(&self, value: T) -> bool; + fn count_leaves(&self) -> usize; fn rotate(&mut self, node: &TreeNode, direction: bool); fn fix_insert_color(&mut self, node: &TreeNode); fn fix_delete_color(&mut self, node: &TreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn count_leaves(&self) -> usize; - fn contains(&self, value: T) -> bool; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -311,6 +311,10 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } + fn count_leaves(&self) -> usize { + self.root.count_leaves() + } + fn rotate(&mut self, node: &TreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); @@ -563,8 +567,4 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!(); } } - - fn count_leaves(&self) -> usize { - self.root.count_leaves() - } } \ No newline at end of file From f59f20e9a66ab654a60bdf97079775053d0041ac Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Sun, 1 Mar 2020 23:09:58 -0700 Subject: [PATCH 60/80] rename --- src/avl_tree.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 00e5de5..ed01baa 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -420,12 +420,12 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D return; } - let mut test = node.left(); + let mut temp = node.left(); if node.left().value().is_none() && node.right().value().is_none() { - test = node.parent(); + temp = node.parent(); } else if node.left().value().is_none() && node.right().value().is_some() { - test = node.right(); + temp = node.right(); } if node.left().value().is_some() && node.right().value().is_some() { @@ -463,7 +463,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D child.set_parent(None); } - self.rebalance(&mut test); + self.rebalance(&mut temp); self.len -= 1; } From e14e0d9c022abaaded38b5fc5b3492a4561b2e20 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Sun, 1 Mar 2020 23:21:10 -0700 Subject: [PATCH 61/80] work on design doc i guess --- design_doc_draft.txt | 64 ++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/design_doc_draft.txt b/design_doc_draft.txt index 6df8008..b457b72 100644 --- a/design_doc_draft.txt +++ b/design_doc_draft.txt @@ -8,37 +8,49 @@ your system’s limitations will score better than letting us find them! o A use Design Rationale -We designed our implementation for the different binary search trees with the goal of providing a reusable crate that could be extended to other types of binary search trees that could potentially be self-balancing. We chose to support: - -[Description of operations here] -- inserting -- deleting -- leaf counting (this is the same for both) -- height of a tree -- in-order print traversal -- is empty? - -Some of the innovations: -- include wrapper functions - encapsulating functionality relating to handling and managing various smart pointers in Rust. Talk about accessing parent/child/sibling/etc -- Using traits to extend and implement commonalities between the RBT and AVL -- Could talk about how some of the binary search functionality for insertion and deletion were re-used. +We designed our implementation of red-black trees and AVL trees with the goal of providing a reusable crates that could be used as a means of something idk. In particular, one of the major innovations of our design involved the user traits, reusable code, and encapsulating functionality associated with smart pointers and their respective operations. [need more detail here on crate stuff, and we actually need to do the crate stuff] + +>> Talk about the traits + struct stuff and impl blocks here like using traits to extend and implement commonalities between the RBT and AVL + +>> Talk about the different operations here + - inserting - start with binary search insert for both + - deleting - start with binary search delete for both, but with slight modification in each binary search (talk about what's a lil different in avl vs rbt) + - leaf counting (this is the same for both) + - height of a tree (same code for both) + - in-order print traversal (same code, only difference is indicating color) + - is empty? (Same code for both, just a wrapper around root.is_none()) + +Our decision to have wrapper functions around operations that involved dealing with smart pointers was ..... Talk about encapsulating functionality with handling/managing smart pointers here because it made code easier to read, maintain, and cleaner. Helped with reducing the amount of repeated code that would have had to be written without. Also talk about how we handled borrows and reference counting stuff with the wrapper functions to access the different nodes of a tree/subtree. + + - Talk about how we specifically chose to implement a top-down approach for insertion in both types of trees so that we could re-use code. Talk about how bottom-up approach maybe for AVL Tree insertion could improve run-time speed with regards to benchmarking. -- Implement concept of smart pointers or something -- something about command line interface -- individual implementations provide different thing -- encapsulate/put library together into a crate and explain why did that -[Explain briefly each of the implemented operations? - how they relate to one another] +>> Talk about command line interface - why we do it the way we have it? +- CLI only takes in numerical values - we can talk about how this decision was made for simple usage but the CLI can be extended to any type of generic value and this could include characters/strings/etc that can be partially ordered, depending on the traits said type implements. + ANSWER FOLLOWING QUESTIONS (maybe combine them with design rationale above?): -What does a red-black tree provide that cannot be accomplished with ordinary binary +- What does a red-black tree provide that cannot be accomplished with ordinary binary search trees? + + - Do you need to apply any kind of error handling in your system (e.g., panic macro, Option, Result, etc..) + +Unless somehow erroneous data is injected into the system, for the most part error handling is not necessarily required. Incorrect or erroneous data that is normally inputted to the system will typically be rejected and would not be allowed to be used in the system, particularly when performing operations on either tree, attempts to insert erroneous data simply will not be handled and will just be rejected/prompt user to attempt to correct themselves. + - What components do the Red-black tree and AVL tree have in common? Don’t Repeat Yourself! Never, ever repeat yourself – a fundamental idea in programming. + +Many of the required components to have had been implemented were identical. The main difference between red-black tree nodes and AVL tree nodes are one field unique to either one. For red-black tree, the color of each node is kept track of, while in AVL, each node keeps track of its height with respect to its depth/distance from the root node. Other than this, both nodes maintain values, and said node's parent and left and right children. Additionally, many of operations that were implemented were simply reused for both tree types. Particularly, counting the number of leaves in a tree, checking if a tree was empty and in-order traversal were essentially identical operations. And although the insert and delete operations for both trees did differ, both implementations required a typical binary search insert and delete respectively, with only a slight modification to either tree at the end which has to do with how both trees self-balance (in red-black tree's case, the color is fixed at the end of inserting/deleting, while for AVL tree, the height of each node is recursively checked to ensure a maintained balance). + - How do we construct our design to “allow it to be efficiently and effectively extended”? For example. Could your code be reused to build a 2-3-4 tree or B tree? +We can construct our design by having the code implement functionality and/or fields that are common between various types of search trees. In the case of binary search trees, the code could be constructed and designed in such a way that the typical binary search insertion and deletion operations are generic and could be extendable such that if there a property/field in a certain type of tree that is to be maintained, that at these operations could still be called/re-used and maintaining whatever said property that is could simply be done after calling the respective binary search operation. This could also be said for the other operations binary search trees have in common (i.e. counting leaves, checking if the tree is empty, and printing via in-order traversal). + +- 2-3-4 trees are essentially an alternate form of red-black trees (i.e. that is, they are equivalent data structures and there is at least 1 analogous red-black tree for every 2-3-4 tree implementation). That being said, it could be possible that our red-black tree code could very much so be re-used to implement a 2-3-4 tree though this could prove to be much more difficult (read more on wikipedia page later lol) +- B trees are unlikely to be able to use our code. Since B trees are a generalized binary search trees in that something about there being allowed to have >2 child nodes. + PART 3 RED BLACK TREE BENCHMARK RESULTS: @@ -59,6 +71,12 @@ Elapsed time for 40000: 31 ms Elapsed time for 70000: 58 ms Elapsed time for 100000: 88 ms Elapsed time for 130000: 114 ms +== +Elapsed time for 10000: 6 ms +Elapsed time for 40000: 30 ms +Elapsed time for 70000: 57 ms +Elapsed time for 100000: 87 ms +Elapsed time for 130000: 113 ms AVL TREE BENCHMARK RESULTS: Elapsed time for 10000: 8 ms @@ -78,6 +96,12 @@ Elapsed time for 40000: 34 ms Elapsed time for 70000: 64 ms Elapsed time for 100000: 98 ms Elapsed time for 130000: 130 ms +== +Elapsed time for 10000: 7 ms +Elapsed time for 40000: 34 ms +Elapsed time for 70000: 64 ms +Elapsed time for 100000: 98 ms +Elapsed time for 130000: 129 ms - AVL is probably going to be more efficient because of height rebalancing factor. - AVL apparently not as efficient (likely to due top-bottom implementation) From a927312b8a61825fc0241e8f847b8d28bdf24ac8 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 10:04:38 -0700 Subject: [PATCH 62/80] refactor delete fix --- src/avl_tree.rs | 14 +++++++------- src/main.rs | 30 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index ed01baa..452ec4b 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -420,12 +420,12 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D return; } - let mut temp = node.left(); - if node.left().value().is_none() && node.right().value().is_none() { - temp = node.parent(); - } - else if node.left().value().is_none() && node.right().value().is_some() { - temp = node.right(); + let mut unbalanced = node.left(); + if node.left().value().is_none() { + unbalanced = match node.right().value() { + None => node.parent(), + Some(_) => node.right(), + }; } if node.left().value().is_some() && node.right().value().is_some() { @@ -463,7 +463,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D child.set_parent(None); } - self.rebalance(&mut temp); + self.rebalance(&mut unbalanced); self.len -= 1; } diff --git a/src/main.rs b/src/main.rs index ee737bd..c1f91a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -161,24 +161,24 @@ fn benchmark_tests() { } fn main() { - loop { - println!("{}", MAIN_MENU); - let choice = get_input(">"); - match choice { - 1 => rbt(), - 2 => avl(), - 3 => benchmark_tests(), - 4 => { - println!("ok bye"); - break; - }, - _ => println!("Invalid input!") - } - } + // loop { + // println!("{}", MAIN_MENU); + // let choice = get_input(">"); + // match choice { + // 1 => rbt(), + // 2 => avl(), + // 3 => benchmark_tests(), + // 4 => { + // println!("ok bye"); + // break; + // }, + // _ => println!("Invalid input!") + // } + // } // it_works(); // print_test(); // delete_cases_2_4(); // test_delete_rbt(); // avl_test(); - // delete_avl(); + delete_avl(); } From 04a86530838c6a3b7ad0c2966f07389d61c21aad Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 14:00:32 -0700 Subject: [PATCH 63/80] get depth but need to refactor so not completely copying song --- src/avl_tree.rs | 35 +++++++++++++++++++++++++++++++++++ src/main.rs | 4 +++- src/red_black_tree.rs | 34 ++++++++++++++++++++++++++++++++++ src/tests.rs | 7 +++++-- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 452ec4b..c359a7a 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -36,6 +36,8 @@ pub trait NodeTraits { fn grandparent(&self) -> AVLTreeNode; fn uncle(&self) -> AVLTreeNode; fn sibling(&self) -> AVLTreeNode; + fn depth(&self) -> Vec>; + fn add_depth(&self, dep: usize, vec: &mut Vec>); // setters for node properties fn set_height(&self, value: isize); // AVL @@ -179,6 +181,28 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } + fn depth(&self) -> Vec> { + let mut deepy: Vec> = Vec::new(); + self.add_depth(0, &mut deepy); + deepy.sort_by(|a, b| b.depth.cmp(&a.depth)); + deepy + } + + fn add_depth(&self, dep: usize, vec: &mut Vec>) { + match self.value() { + Some(_) => { + vec.push(Depth { + value: self.value(), + depth: dep, + }); + self.left().add_depth(dep+1, vec); + self.right().add_depth(dep+1, vec) + } + None => {}, + } + } + + fn set_height(&self, value: isize) { self.unwrapped().borrow_mut().height = value; } @@ -255,6 +279,7 @@ pub trait AVLTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); + fn get_by_depth(&self) -> Vec>; } impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -476,4 +501,14 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D println!(); } } + + fn get_by_depth(&self) -> Vec> { + self.root.depth() + } +} + +#[derive(Debug)] +pub struct Depth { + pub value: Option, + pub depth: usize, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c1f91a8..4a758d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,5 +180,7 @@ fn main() { // delete_cases_2_4(); // test_delete_rbt(); // avl_test(); - delete_avl(); + // delete_avl(); + benchmark_redblack(); + benchmark_avl(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 5c3a95d..4bb33da 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -45,6 +45,8 @@ pub trait NodeTraits { fn grandparent(&self) -> TreeNode; fn uncle(&self) -> TreeNode; fn sibling(&self) -> TreeNode; + fn depth(&self) -> Vec>; + fn add_depth(&self, dep: usize, vec: &mut Vec>); // setters for node properties fn set_color(&self, color: NodeColor); @@ -200,6 +202,27 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } + fn depth(&self) -> Vec> { + let mut deepy: Vec> = Vec::new(); + self.add_depth(0, &mut deepy); + deepy.sort_by(|a, b| b.depth.cmp(&a.depth)); + deepy + } + + fn add_depth(&self, dep: usize, vec: &mut Vec>) { + match self.value() { + Some(_) => { + vec.push(Depth { + value: self.value(), + depth: dep, + }); + self.left().add_depth(dep+1, vec); + self.right().add_depth(dep+1, vec) + } + None => {}, + } + } + fn set_color(&self, color: NodeColor) { self.unwrapped().borrow_mut().color = color; } @@ -277,6 +300,7 @@ pub trait RBTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); + fn get_by_depth(&self) -> Vec>; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -567,4 +591,14 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb println!(); } } + + fn get_by_depth(&self) -> Vec> { + self.root.depth() + } +} + +#[derive(Debug)] +pub struct Depth { + pub value: Option, + pub depth: usize, } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 6618f8a..f3f3075 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -12,10 +12,11 @@ pub fn benchmark_redblack() { tree.insert_node(i); } + let depth = tree.get_by_depth(); let time = std::time::Instant::now(); for i in 0..tree_size/10 { - match tree.contains(i) { + match tree.contains(depth[i as usize].value.unwrap()) { true => { continue; }, false => println!("nope"), } @@ -33,10 +34,12 @@ pub fn benchmark_avl() { tree.insert_node(i); } + let depth = tree.get_by_depth(); let time = std::time::Instant::now(); + for i in 0..tree_size/10 { - match tree.contains(i) { + match tree.contains(depth[i as usize].value.unwrap()) { true => { continue; }, false => println!("nope"), } From 6d5d84ef24f0914e410c523749924d7fbd65a410 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 15:13:18 -0700 Subject: [PATCH 64/80] rename depth stuff --- src/avl_tree.rs | 20 ++++++++--------- src/red_black_tree.rs | 52 +++++++++++++++++++++---------------------- src/tests.rs | 4 ++-- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index c359a7a..a4cd4c0 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -36,8 +36,8 @@ pub trait NodeTraits { fn grandparent(&self) -> AVLTreeNode; fn uncle(&self) -> AVLTreeNode; fn sibling(&self) -> AVLTreeNode; - fn depth(&self) -> Vec>; - fn add_depth(&self, dep: usize, vec: &mut Vec>); + fn get_depth_vec(&self) -> Vec>; + fn calc_depth(&self, dep: usize, vec: &mut Vec>); // setters for node properties fn set_height(&self, value: isize); // AVL @@ -181,22 +181,22 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn depth(&self) -> Vec> { + fn get_depth_vec(&self) -> Vec> { let mut deepy: Vec> = Vec::new(); - self.add_depth(0, &mut deepy); + self.calc_depth(0, &mut deepy); deepy.sort_by(|a, b| b.depth.cmp(&a.depth)); deepy } - fn add_depth(&self, dep: usize, vec: &mut Vec>) { + fn calc_depth(&self, dep: usize, vec: &mut Vec>) { match self.value() { Some(_) => { vec.push(Depth { value: self.value(), depth: dep, }); - self.left().add_depth(dep+1, vec); - self.right().add_depth(dep+1, vec) + self.left().calc_depth(dep+1, vec); + self.right().calc_depth(dep+1, vec) } None => {}, } @@ -279,7 +279,7 @@ pub trait AVLTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn get_by_depth(&self) -> Vec>; + fn get_depth_vec(&self) -> Vec>; } impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -502,8 +502,8 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } } - fn get_by_depth(&self) -> Vec> { - self.root.depth() + fn get_depth_vec(&self) -> Vec> { + self.root.get_depth_vec() } } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 4bb33da..12d0487 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -35,6 +35,8 @@ pub trait NodeTraits { fn count_leaves(&self) -> usize; fn is_red(&self) -> bool; fn is_black(&self) -> bool; + fn get_depth_vec(&self) -> Vec>; + fn calc_depth(&self, dep: usize, vec: &mut Vec>); // getters for node properties and family members fn color(&self) -> NodeColor; @@ -45,8 +47,6 @@ pub trait NodeTraits { fn grandparent(&self) -> TreeNode; fn uncle(&self) -> TreeNode; fn sibling(&self) -> TreeNode; - fn depth(&self) -> Vec>; - fn add_depth(&self, dep: usize, vec: &mut Vec>); // setters for node properties fn set_color(&self, color: NodeColor); @@ -146,6 +146,27 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb self.color() == NodeColor::Black } + fn get_depth_vec(&self) -> Vec> { + let mut vec: Vec> = Vec::new(); + self.calc_depth(0, &mut vec); + vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + vec + } + + fn calc_depth(&self, dep: usize, vec: &mut Vec>) { + match self.value() { + Some(_) => { + vec.push(Depth { + value: self.value(), + depth: dep, + }); + self.left().calc_depth(dep+1, vec); + self.right().calc_depth(dep+1, vec) + } + None => {}, + } + } + fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -202,27 +223,6 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn depth(&self) -> Vec> { - let mut deepy: Vec> = Vec::new(); - self.add_depth(0, &mut deepy); - deepy.sort_by(|a, b| b.depth.cmp(&a.depth)); - deepy - } - - fn add_depth(&self, dep: usize, vec: &mut Vec>) { - match self.value() { - Some(_) => { - vec.push(Depth { - value: self.value(), - depth: dep, - }); - self.left().add_depth(dep+1, vec); - self.right().add_depth(dep+1, vec) - } - None => {}, - } - } - fn set_color(&self, color: NodeColor) { self.unwrapped().borrow_mut().color = color; } @@ -300,7 +300,7 @@ pub trait RBTreeTraits { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn get_by_depth(&self) -> Vec>; + fn get_depth_vec(&self) -> Vec>; } impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { @@ -592,8 +592,8 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - fn get_by_depth(&self) -> Vec> { - self.root.depth() + fn get_depth_vec(&self) -> Vec> { + self.root.get_depth_vec() } } diff --git a/src/tests.rs b/src/tests.rs index f3f3075..e8a731a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -12,7 +12,7 @@ pub fn benchmark_redblack() { tree.insert_node(i); } - let depth = tree.get_by_depth(); + let depth = tree.get_depth_vec(); let time = std::time::Instant::now(); for i in 0..tree_size/10 { @@ -34,7 +34,7 @@ pub fn benchmark_avl() { tree.insert_node(i); } - let depth = tree.get_by_depth(); + let depth = tree.get_depth_vec(); let time = std::time::Instant::now(); From 10fd260100cebc27b2f4f2be901c68862b58a4be Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Mon, 2 Mar 2020 15:26:48 -0700 Subject: [PATCH 65/80] cleaned up tests --- src/tests.rs | 386 ++++++++++----------------------------------------- 1 file changed, 77 insertions(+), 309 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index e8a731a..a836604 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -70,188 +70,47 @@ pub fn it_works() { println!("no leaves = {}", rbt.count_leaves()); println!(); - println!("Inserting 5 ..."); - rbt.insert_node(5); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height with 1 node = {}", rbt.height()); - println!("1 node = 1 leaf? = {}", rbt.count_leaves()); - println!(); - - // HEIGHTS ARE OFF BY ONE AND IDK WHY YET - println!("Inserting 70 ..."); - rbt.insert_node(70); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!(); - - println!("Inserting 35 ..."); - rbt.insert_node(35); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("3 nodes = 2 leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 8 ..."); - rbt.insert_node(8); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 100 ..."); - rbt.insert_node(100); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 60 ..."); - rbt.insert_node(60); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 120 ..."); - rbt.insert_node(120); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 1 ..."); - rbt.insert_node(1); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 84 ..."); - rbt.insert_node(84); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - println!("Inserting 17 ..."); - rbt.insert_node(17); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("num leaves = {}", rbt.count_leaves()); - println!(); - - assert!(rbt.search(35).is_some()); - assert!(rbt.search(5).is_some()); - assert!(rbt.search(1).is_some()); - assert!(rbt.search(8).is_some()); - assert!(rbt.search(17).is_some()); - assert!(rbt.search(60).is_some()); - assert!(rbt.search(70).is_some()); - assert!(rbt.search(84).is_some()); - assert!(rbt.search(100).is_some()); - assert!(rbt.search(120).is_some()); + let mut vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; + for &x in vec_in.iter() { + println!("Inserting {} ...", x); + rbt.insert_node(x); + println!("size = {}", rbt.size()); + rbt.print(); + println!("height = {}", rbt.height()); + println!("number of leaves = {}", rbt.count_leaves()); + println!(); + } + vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; + for &x in vec_in.iter() { + assert!(rbt.search(x).is_some()); + assert!(rbt.contains(x) == true); + } assert!(rbt.search(10).is_none()); - - assert!(rbt.contains(35) == true); - assert!(rbt.contains(5) == true); - assert!(rbt.contains(1) == true); - assert!(rbt.contains(8) == true); - assert!(rbt.contains(17) == true); - assert!(rbt.contains(60) == true); - assert!(rbt.contains(70) == true); - assert!(rbt.contains(84) == true); - assert!(rbt.contains(100) == true); - assert!(rbt.contains(120) == true); assert!(rbt.contains(10) == false); - // println!("Deleting 1 ..."); - // rbt.delete_node(1); - // println!("size = {}", rbt.size()); - // rbt.print(); - // println!("height = {}", rbt.height()); - // println!("num leaves = {}", rbt.count_leaves()); - // println!(); - println!("\n==== Start Testing DELETE RBTree Here ====\n"); let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let mut vec_in = vec![30, 20, 40, 10, 50]; + for &x in vec_in.iter() { + println!("Inserting {} ...", x); + rbt2.insert_node(x); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + } - println!("Inserting 30 ..."); - rbt2.insert_node(30); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Inserting 20 ..."); - rbt2.insert_node(20); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Inserting 40 ..."); - rbt2.insert_node(40); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Inserting 10 ..."); - rbt2.insert_node(10); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Deleting 10 ..."); - rbt2.delete_node(10); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("num leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Inserting 50 ..."); - rbt2.insert_node(50); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Deleting 20 ..."); - rbt2.delete_node(20); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("num leaves = {}", rbt2.count_leaves()); - println!(); - - println!("Deleting 30 ..."); - rbt2.delete_node(30); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("num leaves = {}", rbt2.count_leaves()); - println!(); - - - - + vec_in = vec![10, 20, 30]; + for &x in vec_in.iter() { + println!("Deleting {} ...", x); + rbt2.delete_node(x); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); + } } pub fn test_delete_rbt() { @@ -267,19 +126,11 @@ pub fn test_delete_rbt() { println!("deleting everything .."); - rbt.delete_node(6); - // rbt.print(); - rbt.delete_node(4); - // rbt.print(); - rbt.delete_node(2); - // rbt.print(); - rbt.delete_node(8); - rbt.delete_node(9); - rbt.delete_node(7); - rbt.delete_node(3); - rbt.delete_node(1); - rbt.delete_node(5); - rbt.delete_node(10); + let mut vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + rbt.delete_node(x); + } assert!(rbt.is_empty() == true); rbt.print(); } @@ -292,22 +143,12 @@ pub fn delete_cases_1_3_5_6() { println!("inserting ... {}", x); } - - rbt.delete_node(4); - // rbt.print(); - rbt.delete_node(6); - rbt.print(); - rbt.delete_node(8); - // rbt.print(); - rbt.delete_node(1); - rbt.print(); - // println!("-----------------------------PRINTING DELETING 5"); - rbt.delete_node(5); - rbt.print(); - rbt.delete_node(9); - rbt.delete_node(2); - rbt.print(); - + let mut vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; + for &x in vec_in.iter() { + println!("deleting ... {}", x); + rbt.delete_node(x); + rbt.print(); + } } pub fn delete_cases_2_4() { @@ -336,58 +177,36 @@ pub fn delete_cases_2_4() { println!("leaves = {}", rbt.count_leaves()); println!(); } +} +pub fn avl_test() { + println!("\n==== Start Testing AVLTree Here ====\n"); - - - } - - pub fn avl_test() { - // let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - //let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - - println!("\n==== Start Testing AVLTree Here ====\n"); - - let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - // let mut vec_in: Vec = vec![5, 70, 35]; // right left //, 8, 98, 60]; // poop on 99];//, 8, 98, 60, 99, 99, 1, 84, 17]; - // let mut vec_in: Vec = vec![5, 3, 1]; // left left - // let mut vec_in: Vec = vec![5, 1, 3]; // left right - // let mut vec_in: Vec = vec![5, 70, 90]; // right right - let mut vec_in: Vec = vec![5, 70, 35, 98, 98, 60, 99, 99, 1, 84, 17];//, 98, 60]; - - println!("AVL Tree INIT = {:?}", avl); - for &x in vec_in.iter() { - println!("inserting {} ...", x); - avl.insert_node(x); - // println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); - } - - println!("inserting {} ...", 98); - avl.insert_node(98); - // println!("size is now = {}", avl.size()); + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + for &x in vec_in.iter() { + println!("inserting {} ...", x); + avl.insert_node(x); + println!("size is now = {}", avl.size()); avl.print(); println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); println!(); + } + vec_in = vec![17, 84, 99, 5, 1, 60]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + avl.delete_node(x); + println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + } +} - - // vec_in = vec![17, 84, 99, 5, 1, 60]; - // for &x in vec_in.iter() { - // println!("deleting {} ...", x); - // avl.delete_node(x); - // println!("size is now = {}", avl.size()); - // avl.print(); - // println!("height = {}", avl.height()); - // println!("leaves = {}", avl.count_leaves()); - // println!(); - // } - } - pub fn delete_avl() { +pub fn delete_avl() { let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); for x in 1..=10 { @@ -398,66 +217,15 @@ pub fn delete_cases_2_4() { println!("height = {}", avl.height()); println!("leaves = {}", avl.count_leaves()); println!("=========================="); - println!("deleting {} ...", 4); - avl.delete_node(4); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 5); - avl.delete_node(5); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 8); - avl.delete_node(8); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 7); - avl.delete_node(7); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 3); - avl.delete_node(3); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 2); - avl.delete_node(2); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 1); - avl.delete_node(1); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 9); - avl.delete_node(9); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 6); - avl.delete_node(6); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - println!("deleting {} ...", 10); - avl.delete_node(10); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); + let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + avl.delete_node(x); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + } println!(); - } \ No newline at end of file From 7e5eca604c176341b180dffcb0b341f34b310ad5 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 16:05:14 -0700 Subject: [PATCH 66/80] start to make general thingies --- src/main.rs | 8 +- src/red_black_tree.rs | 231 +++++++++++++++++++++--------------------- src/tests.rs | 3 +- src/tree.rs | 32 ++++++ 4 files changed, 152 insertions(+), 122 deletions(-) create mode 100644 src/tree.rs diff --git a/src/main.rs b/src/main.rs index 4a758d1..ccf8f69 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,12 @@ mod avl_tree; mod red_black_tree; mod tests; +mod tree; use red_black_tree::*; use avl_tree::*; use tests::*; +// use tree::TreeBase; use std::io::{stdin, stdout, Write}; @@ -175,12 +177,12 @@ fn main() { // _ => println!("Invalid input!") // } // } - // it_works(); + it_works(); // print_test(); // delete_cases_2_4(); // test_delete_rbt(); // avl_test(); // delete_avl(); - benchmark_redblack(); - benchmark_avl(); + // benchmark_redblack(); + // benchmark_avl(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 12d0487..1f1a10a 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use crate::tree::{TreeBase, NodeTraits, Depth}; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -13,52 +14,106 @@ pub enum NodeColor { Black, } -pub type TreeNode = Option>>>; +pub type RBTreeNode = Option>>>; #[derive(Debug)] -pub struct Node { +pub struct RBTNode { color: NodeColor, value: Option, - parent: TreeNode, - left: TreeNode, - right: TreeNode + parent: RBTreeNode, + left: RBTreeNode, + right: RBTreeNode } -pub trait NodeTraits { +pub trait RBTNodeTraits { // helper functions - fn new(val: T) -> TreeNode; - fn unwrapped(&self) -> Rc>>; - fn compare(&self, node: &TreeNode) -> bool; - fn find_node(&self, value: T) -> TreeNode; + fn new(val: T) -> RBTreeNode; + fn unwrapped(&self) -> Rc>>; + fn compare(&self, node: &RBTreeNode) -> bool; + fn find_node(&self, value: T) -> RBTreeNode; fn node_height(&self) -> usize; - fn print_traversal(&self); - fn count_leaves(&self) -> usize; + + // RBT specific helper functions fn is_red(&self) -> bool; fn is_black(&self) -> bool; - fn get_depth_vec(&self) -> Vec>; - fn calc_depth(&self, dep: usize, vec: &mut Vec>); - - // getters for node properties and family members - fn color(&self) -> NodeColor; - fn value(&self) -> Option; - fn parent(&self) -> TreeNode; - fn left(&self) -> TreeNode; - fn right(&self) -> TreeNode; - fn grandparent(&self) -> TreeNode; - fn uncle(&self) -> TreeNode; - fn sibling(&self) -> TreeNode; + + // getters for family members and node property + fn parent(&self) -> RBTreeNode; + fn left(&self) -> RBTreeNode; + fn right(&self) -> RBTreeNode; + fn grandparent(&self) -> RBTreeNode; + fn uncle(&self) -> RBTreeNode; + fn sibling(&self) -> RBTreeNode; + fn color(&self) -> NodeColor; // RBT specific node property // setters for node properties - fn set_color(&self, color: NodeColor); - fn set_value(&self, value: T); - fn set_parent(&mut self, parent: TreeNode); - fn set_left(&mut self, left: TreeNode); - fn set_right(&mut self, right: TreeNode); + fn set_parent(&mut self, parent: RBTreeNode); + fn set_left(&mut self, left: RBTreeNode); + fn set_right(&mut self, right: RBTreeNode); + fn set_color(&self, color: NodeColor); // RBT specific node property } -impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Debug { - fn new(val: T) -> TreeNode { - let tree_node = Some(Rc::new(RefCell::new(Node { +impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + fn print_traversal(&self) { + if self.is_some() && self.value().is_some() { + self.left().print_traversal(); + if self.is_red() { + print!("<{:?}>", self.value().unwrap()); + } else { + print!("[{:?}]", self.value().unwrap()); + } + self.right().print_traversal(); + } + } + + fn count_leaves(&self) -> usize { + if self.value().is_none() { + 0 + } else if self.left().value().is_none() && self.right().value().is_none() { + 1 + } else { + self.left().count_leaves() + self.right().count_leaves() + } + } + + fn get_depth_vec(&self) -> Vec> { + let mut vec: Vec> = Vec::new(); + self.calc_depth(0, &mut vec); + vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + vec + } + + fn calc_depth(&self, dep: usize, vec: &mut Vec>) { + match self.value() { + Some(_) => { + vec.push(Depth { + value: self.value(), + depth: dep, + }); + self.left().calc_depth(dep+1, vec); + self.right().calc_depth(dep+1, vec) + } + None => {}, + } + } + + // required getters for node properties + fn value(&self) -> Option { + match self { + Some(tree_node) => tree_node.borrow().value, + None => None + } + } + + // setters for node properties + fn set_value(&self, value: T) { + self.unwrapped().borrow_mut().value = Some(value); + } +} + +impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + fn new(val: T) -> RBTreeNode { + let tree_node = Some(Rc::new(RefCell::new(RBTNode { color: NodeColor::Red, value: Some(val), parent: None, @@ -71,21 +126,21 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb tree_node } - fn unwrapped(&self) -> Rc>> { + fn unwrapped(&self) -> Rc>> { match self { Some(tree_node) => Rc::clone(&tree_node), None => panic!("Error unwrapping tree node") } } - fn compare(&self, node: &TreeNode) -> bool { + fn compare(&self, node: &RBTreeNode) -> bool { if self.is_none() || node.is_none() { return false } Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } - fn find_node(&self, value: T) -> TreeNode { + fn find_node(&self, value: T) -> RBTreeNode { match self.value() { Some(_) => { if value == self.value().unwrap() { @@ -116,28 +171,6 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn print_traversal(&self) { - if self.is_some() && self.value().is_some() { - self.left().print_traversal(); - if self.is_red() { - print!("<{:?}>", self.value().unwrap()); - } else { - print!("[{:?}]", self.value().unwrap()); - } - self.right().print_traversal(); - } - } - - fn count_leaves(&self) -> usize { - if self.value().is_none() { - 0 - } else if self.left().value().is_none() && self.right().value().is_none() { - 1 - } else { - self.left().count_leaves() + self.right().count_leaves() - } - } - fn is_red(&self) -> bool { self.color() == NodeColor::Red } @@ -146,27 +179,6 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb self.color() == NodeColor::Black } - fn get_depth_vec(&self) -> Vec> { - let mut vec: Vec> = Vec::new(); - self.calc_depth(0, &mut vec); - vec.sort_by(|a, b| b.depth.cmp(&a.depth)); - vec - } - - fn calc_depth(&self, dep: usize, vec: &mut Vec>) { - match self.value() { - Some(_) => { - vec.push(Depth { - value: self.value(), - depth: dep, - }); - self.left().calc_depth(dep+1, vec); - self.right().calc_depth(dep+1, vec) - } - None => {}, - } - } - fn color(&self) -> NodeColor { match self { Some(tree_node) => tree_node.borrow().color.clone(), @@ -174,39 +186,32 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn value(&self) -> Option { - match self { - Some(tree_node) => tree_node.borrow().value, - None => None - } - } - - fn parent(&self) -> TreeNode { + fn parent(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().parent.clone(), None => None } } - fn left(&self) -> TreeNode { + fn left(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().left.clone(), None => None } } - fn right(&self) -> TreeNode { + fn right(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().right.clone(), None => None } } - fn grandparent(&self) -> TreeNode { + fn grandparent(&self) -> RBTreeNode { self.parent().parent() } - fn uncle(&self) -> TreeNode { + fn uncle(&self) -> RBTreeNode { if self.grandparent().left().is_none() || self.grandparent().right().is_none() { None } else if self.parent().compare(&self.grandparent().left()) { @@ -216,7 +221,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn sibling(&self) -> TreeNode { + fn sibling(&self) -> RBTreeNode { match self.compare(&self.parent().left()) { true => self.parent().right(), false => self.parent().left(), @@ -227,14 +232,10 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb self.unwrapped().borrow_mut().color = color; } - fn set_value(&self, value: T) { - self.unwrapped().borrow_mut().value = Some(value); - } - - fn set_parent(&mut self, parent: TreeNode) { + fn set_parent(&mut self, parent: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().parent = parent, - None => *self = Some(Rc::new(RefCell::new(Node { + None => *self = Some(Rc::new(RefCell::new(RBTNode { color: self.color(), value: self.value(), parent: parent, @@ -244,10 +245,10 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn set_left(&mut self, left: TreeNode) { + fn set_left(&mut self, left: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().left = left, - None => *self = Some(Rc::new(RefCell::new(Node { + None => *self = Some(Rc::new(RefCell::new(RBTNode { color: self.color(), value: self.value(), parent: self.parent(), @@ -257,10 +258,10 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb } } - fn set_right(&mut self, right: TreeNode) { + fn set_right(&mut self, right: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().right = right, - None => *self = Some(Rc::new(RefCell::new(Node { + None => *self = Some(Rc::new(RefCell::new(RBTNode { color: self.color(), value: self.value(), parent: self.parent(), @@ -274,7 +275,7 @@ impl NodeTraits for TreeNode where T: Copy + PartialOrd + std::fmt::Deb /******************** RBTree Helpers ********************/ pub struct RBTree { - root: TreeNode, + root: RBTreeNode, len: usize } @@ -291,12 +292,12 @@ pub trait RBTreeTraits { fn height(&self) -> usize; fn is_empty(&self) -> bool; fn size(&self) -> usize; - fn search(&self, value: T) -> TreeNode; + fn search(&self, value: T) -> RBTreeNode; fn contains(&self, value: T) -> bool; fn count_leaves(&self) -> usize; - fn rotate(&mut self, node: &TreeNode, direction: bool); - fn fix_insert_color(&mut self, node: &TreeNode); - fn fix_delete_color(&mut self, node: &TreeNode); + fn rotate(&mut self, node: &RBTreeNode, direction: bool); + fn fix_insert_color(&mut self, node: &RBTreeNode); + fn fix_delete_color(&mut self, node: &RBTreeNode); fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); @@ -324,7 +325,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len } - fn search(&self, value: T) -> TreeNode { + fn search(&self, value: T) -> RBTreeNode { self.root.find_node(value) } @@ -339,7 +340,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.root.count_leaves() } - fn rotate(&mut self, node: &TreeNode, direction: bool) { + fn rotate(&mut self, node: &RBTreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); let mut node = node.clone(); @@ -371,7 +372,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } - fn fix_insert_color(&mut self, node: &TreeNode) { + fn fix_insert_color(&mut self, node: &RBTreeNode) { // CASE 1 if node.compare(&self.root) { node.set_color(NodeColor::Black); @@ -418,7 +419,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } fn insert_node(&mut self, value: T) { - let mut new_node = TreeNode::new(value); + let mut new_node = RBTreeNode::new(value); if self.is_empty() { self.root = new_node.clone(); @@ -428,7 +429,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb return; } else { let mut curr_node = self.root.clone(); - let mut curr_node_parent: TreeNode = None; + let mut curr_node_parent: RBTreeNode = None; let mut is_left_child = true; // find empty node @@ -460,7 +461,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len += 1; } - fn fix_delete_color(&mut self, node: &TreeNode) { + fn fix_delete_color(&mut self, node: &RBTreeNode) { // CASE 1: node is root so done (it’s already black) if node.compare(&self.root) { return; @@ -595,10 +596,4 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb fn get_depth_vec(&self) -> Vec> { self.root.get_depth_vec() } -} - -#[derive(Debug)] -pub struct Depth { - pub value: Option, - pub depth: usize, } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index e8a731a..04221c3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,5 +1,6 @@ use super::*; use avl_tree::AVLTreeTraits; +use crate::tree::NodeTraits; // #[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main @@ -51,7 +52,7 @@ pub fn benchmark_avl() { pub fn it_works() { // Test TreeNode - let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); + let treenode: red_black_tree::RBTreeNode = red_black_tree::RBTreeNode::new(5); println!("{:?}", treenode.value()); println!("{:?}", treenode.color()); diff --git a/src/tree.rs b/src/tree.rs new file mode 100644 index 0000000..d6f1f62 --- /dev/null +++ b/src/tree.rs @@ -0,0 +1,32 @@ +#[derive(Debug)] +pub struct Depth { + pub value: Option, + pub depth: usize, +} + +pub trait NodeTraits { + // required/default helper functions + fn print_traversal(&self); + fn count_leaves(&self) -> usize; + fn get_depth_vec(&self) -> Vec>; + fn calc_depth(&self, dep: usize, vec: &mut Vec>); + + // required getters for node properties + fn value(&self) -> Option; + + // setters for node properties + fn set_value(&self, value: T); +} + +pub trait TreeBase { + fn height(&self) -> usize; + fn is_empty(&self) -> bool; + fn size(&self) -> usize; + fn contains(&self, value: T) -> bool; + fn count_leaves(&self) -> usize; + fn insert_node(&mut self, value: T); + fn delete_node(&mut self, value: T); + fn print(&self); + fn get_by_depth(&self) -> Vec>; +} + From ce54214e52f632126c41138bbe43032c12c37ae5 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Mon, 2 Mar 2020 16:32:10 -0700 Subject: [PATCH 67/80] updated cli --- src/main.rs | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4a758d1..66a0db3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,14 +84,14 @@ fn avl() { println!("Error deleting value"); } }, - 3 => println!("{}", avl.count_leaves()), - 4 => println!("{}", avl.height()), + 3 => println!("Number of leaves: {}", avl.count_leaves()), + 4 => println!("Height: {}", avl.height()), 5 => avl.print(), 6 => { if avl.is_empty() { println!("Tree is empty."); } else { - println!("nah tree is full of leaves"); + println!("Nah tree is full of leaves"); } }, 7 => break, @@ -127,14 +127,14 @@ fn rbt() { println!("Error deleting value"); } }, - 3 => println!("{}", rbt.count_leaves()), - 4 => println!("{}", rbt.height()), + 3 => println!("Number of leaves: {}", rbt.count_leaves()), + 4 => println!("Height: {}", rbt.height()), 5 => rbt.print(), 6 => { if rbt.is_empty() { println!("Tree is empty."); } else { - println!("nah tree is full of leaves"); + println!("Nah tree is full of leaves"); } } 7 => break, @@ -148,12 +148,8 @@ fn benchmark_tests() { println!("{}", BENCHMARK_MENU); let choice = get_input(">"); match choice { - 1 => { - benchmark_redblack(); - }, - 2 => { - benchmark_avl(); - }, + 1 => benchmark_redblack(), + 2 => benchmark_avl(), 3 => break, _ => println!("Invalid input!") } @@ -161,26 +157,26 @@ fn benchmark_tests() { } fn main() { - // loop { - // println!("{}", MAIN_MENU); - // let choice = get_input(">"); - // match choice { - // 1 => rbt(), - // 2 => avl(), - // 3 => benchmark_tests(), - // 4 => { - // println!("ok bye"); - // break; - // }, - // _ => println!("Invalid input!") - // } - // } + loop { + println!("{}", MAIN_MENU); + let choice = get_input(">"); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => benchmark_tests(), + 4 => { + println!("ok bye"); + break; + }, + _ => println!("Invalid input!") + } + } // it_works(); // print_test(); // delete_cases_2_4(); // test_delete_rbt(); // avl_test(); // delete_avl(); - benchmark_redblack(); - benchmark_avl(); + // benchmark_redblack(); + // benchmark_avl(); } From c0bd9d2aa02431f472ae76e117565d39c04558c9 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Mon, 2 Mar 2020 16:35:08 -0700 Subject: [PATCH 68/80] temporarily commented out stuff for video --- src/tests.rs | 354 +++++++++++++++++++++++++-------------------------- 1 file changed, 177 insertions(+), 177 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index a836604..e162e01 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -49,183 +49,183 @@ pub fn benchmark_avl() { } } -pub fn it_works() { - // Test TreeNode - let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); +// pub fn it_works() { +// // Test TreeNode +// let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); - println!("{:?}", treenode.value()); - println!("{:?}", treenode.color()); - - treenode.set_color(red_black_tree::NodeColor::Black); - println!("{:?}", treenode.color()); - - treenode.set_value(10); - println!("{:?}", treenode.value()); - - - // Test RBTree - println!("\n==== Start Testing RBTree Here ====\n"); - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - println!("empty height = {}", rbt.height()); - println!("no leaves = {}", rbt.count_leaves()); - println!(); - - let mut vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; - for &x in vec_in.iter() { - println!("Inserting {} ...", x); - rbt.insert_node(x); - println!("size = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("number of leaves = {}", rbt.count_leaves()); - println!(); - } - vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; - for &x in vec_in.iter() { - assert!(rbt.search(x).is_some()); - assert!(rbt.contains(x) == true); - } - assert!(rbt.search(10).is_none()); - assert!(rbt.contains(10) == false); - - println!("\n==== Start Testing DELETE RBTree Here ====\n"); - let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); - let mut vec_in = vec![30, 20, 40, 10, 50]; - for &x in vec_in.iter() { - println!("Inserting {} ...", x); - rbt2.insert_node(x); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); - } - - vec_in = vec![10, 20, 30]; - for &x in vec_in.iter() { - println!("Deleting {} ...", x); - rbt2.delete_node(x); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("num leaves = {}", rbt2.count_leaves()); - println!(); - } -} - -pub fn test_delete_rbt() { - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - - for x in 1..=10 { - rbt.insert_node(x); - println!("inserting ... {}", x); - } - - assert!(rbt.is_empty() == false); - rbt.print(); - - println!("deleting everything .."); - - let mut vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; - for &x in vec_in.iter() { - println!("deleting {} ...", x); - rbt.delete_node(x); - } - assert!(rbt.is_empty() == true); - rbt.print(); -} - -pub fn delete_cases_1_3_5_6() { - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// println!("{:?}", treenode.value()); +// println!("{:?}", treenode.color()); + +// treenode.set_color(red_black_tree::NodeColor::Black); +// println!("{:?}", treenode.color()); + +// treenode.set_value(10); +// println!("{:?}", treenode.value()); + + +// // Test RBTree +// println!("\n==== Start Testing RBTree Here ====\n"); +// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// println!("empty height = {}", rbt.height()); +// println!("no leaves = {}", rbt.count_leaves()); +// println!(); + +// let mut vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; +// for &x in vec_in.iter() { +// println!("Inserting {} ...", x); +// rbt.insert_node(x); +// println!("size = {}", rbt.size()); +// rbt.print(); +// println!("height = {}", rbt.height()); +// println!("number of leaves = {}", rbt.count_leaves()); +// println!(); +// } +// vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; +// for &x in vec_in.iter() { +// assert!(rbt.search(x).is_some()); +// assert!(rbt.contains(x) == true); +// } +// assert!(rbt.search(10).is_none()); +// assert!(rbt.contains(10) == false); + +// println!("\n==== Start Testing DELETE RBTree Here ====\n"); +// let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// let mut vec_in = vec![30, 20, 40, 10, 50]; +// for &x in vec_in.iter() { +// println!("Inserting {} ...", x); +// rbt2.insert_node(x); +// println!("size = {}", rbt2.size()); +// rbt2.print(); +// println!("height = {}", rbt2.height()); +// println!("leaves = {}", rbt2.count_leaves()); +// println!(); +// } + +// vec_in = vec![10, 20, 30]; +// for &x in vec_in.iter() { +// println!("Deleting {} ...", x); +// rbt2.delete_node(x); +// println!("size = {}", rbt2.size()); +// rbt2.print(); +// println!("height = {}", rbt2.height()); +// println!("num leaves = {}", rbt2.count_leaves()); +// println!(); +// } +// } + +// pub fn test_delete_rbt() { +// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + +// for x in 1..=10 { +// rbt.insert_node(x); +// println!("inserting ... {}", x); +// } + +// assert!(rbt.is_empty() == false); +// rbt.print(); + +// println!("deleting everything .."); + +// let mut vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; +// for &x in vec_in.iter() { +// println!("deleting {} ...", x); +// rbt.delete_node(x); +// } +// assert!(rbt.is_empty() == true); +// rbt.print(); +// } + +// pub fn delete_cases_1_3_5_6() { +// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - for x in 1..=10 { - rbt.insert_node(x); - println!("inserting ... {}", x); - } - - let mut vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; - for &x in vec_in.iter() { - println!("deleting ... {}", x); - rbt.delete_node(x); - rbt.print(); - } -} - -pub fn delete_cases_2_4() { - println!("\n==== Start Testing DELETE RBTree Here ====\n"); - - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; - - for &x in vec_in.iter() { - println!("inserting {} ...", x); - rbt.insert_node(x); - println!("size is now = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("leaves = {}", rbt.count_leaves()); - println!(); - } - - vec_in = vec![17, 84, 99, 5, 1, 60]; - for &x in vec_in.iter() { - println!("deleting {} ...", x); - rbt.delete_node(x); - println!("size is now = {}", rbt.size()); - rbt.print(); - println!("height = {}", rbt.height()); - println!("leaves = {}", rbt.count_leaves()); - println!(); - } -} - -pub fn avl_test() { - println!("\n==== Start Testing AVLTree Here ====\n"); - - let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; - for &x in vec_in.iter() { - println!("inserting {} ...", x); - avl.insert_node(x); - println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); - } - - vec_in = vec![17, 84, 99, 5, 1, 60]; - for &x in vec_in.iter() { - println!("deleting {} ...", x); - avl.delete_node(x); - println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); - } -} - -pub fn delete_avl() { - let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); +// for x in 1..=10 { +// rbt.insert_node(x); +// println!("inserting ... {}", x); +// } + +// let mut vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; +// for &x in vec_in.iter() { +// println!("deleting ... {}", x); +// rbt.delete_node(x); +// rbt.print(); +// } +// } + +// pub fn delete_cases_2_4() { +// println!("\n==== Start Testing DELETE RBTree Here ====\n"); + +// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + +// for &x in vec_in.iter() { +// println!("inserting {} ...", x); +// rbt.insert_node(x); +// println!("size is now = {}", rbt.size()); +// rbt.print(); +// println!("height = {}", rbt.height()); +// println!("leaves = {}", rbt.count_leaves()); +// println!(); +// } + +// vec_in = vec![17, 84, 99, 5, 1, 60]; +// for &x in vec_in.iter() { +// println!("deleting {} ...", x); +// rbt.delete_node(x); +// println!("size is now = {}", rbt.size()); +// rbt.print(); +// println!("height = {}", rbt.height()); +// println!("leaves = {}", rbt.count_leaves()); +// println!(); +// } +// } + +// pub fn avl_test() { +// println!("\n==== Start Testing AVLTree Here ====\n"); + +// let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); +// let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; +// for &x in vec_in.iter() { +// println!("inserting {} ...", x); +// avl.insert_node(x); +// println!("size is now = {}", avl.size()); +// avl.print(); +// println!("height = {}", avl.height()); +// println!("leaves = {}", avl.count_leaves()); +// println!(); +// } + +// vec_in = vec![17, 84, 99, 5, 1, 60]; +// for &x in vec_in.iter() { +// println!("deleting {} ...", x); +// avl.delete_node(x); +// println!("size is now = {}", avl.size()); +// avl.print(); +// println!("height = {}", avl.height()); +// println!("leaves = {}", avl.count_leaves()); +// println!(); +// } +// } + +// pub fn delete_avl() { +// let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); - for x in 1..=10 { - avl.insert_node(x); - println!("inserting ... {}", x); - } - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!("=========================="); - - let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; - for &x in vec_in.iter() { - println!("deleting {} ...", x); - avl.delete_node(x); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); - } - println!(); -} \ No newline at end of file +// for x in 1..=10 { +// avl.insert_node(x); +// println!("inserting ... {}", x); +// } +// avl.print(); +// println!("height = {}", avl.height()); +// println!("leaves = {}", avl.count_leaves()); +// println!("=========================="); + +// let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; +// for &x in vec_in.iter() { +// println!("deleting {} ...", x); +// avl.delete_node(x); +// println!("height = {}", avl.height()); +// println!("leaves = {}", avl.count_leaves()); +// avl.print(); +// println!("=========================="); +// } +// println!(); +// } \ No newline at end of file From fc664bc575d49e518ed8ab76a17961fbb3d2d606 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 16:42:49 -0700 Subject: [PATCH 69/80] done refactor i think --- src/avl_tree.rs | 132 +++++++++++----------- src/main.rs | 8 +- src/red_black_tree.rs | 255 +++++++++++++++++++++--------------------- src/tests.rs | 7 +- test.txt | 0 5 files changed, 201 insertions(+), 201 deletions(-) create mode 100644 test.txt diff --git a/src/avl_tree.rs b/src/avl_tree.rs index a4cd4c0..c964479 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -1,6 +1,7 @@ use std::cell::RefCell; use std::rc::Rc; use std::cmp::max; +use crate::tree::{TreeBase, NodeTraits, Depth}; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -16,38 +17,90 @@ pub struct AVLNode { height: isize, } -pub trait NodeTraits { +pub trait AVLNodeTraits { // helper functions fn new(val: T) -> AVLTreeNode; fn unwrapped(&self) -> Rc>>; fn compare(&self, node: &AVLTreeNode) -> bool; fn find_node(&self, value: T) -> AVLTreeNode; - fn print_traversal(&self); - fn count_leaves(&self) -> usize; - fn recalc_height(&mut self); // AVL - fn get_balance(&self) -> isize; // AVL + + // AVL specific helper functions + fn recalc_height(&mut self); + fn get_balance(&self) -> isize; // getters for node properties and family members - fn height(&self) -> isize; // AVL - fn value(&self) -> Option; + fn parent(&self) -> AVLTreeNode; fn left(&self) -> AVLTreeNode; fn right(&self) -> AVLTreeNode; fn grandparent(&self) -> AVLTreeNode; fn uncle(&self) -> AVLTreeNode; fn sibling(&self) -> AVLTreeNode; - fn get_depth_vec(&self) -> Vec>; - fn calc_depth(&self, dep: usize, vec: &mut Vec>); + fn height(&self) -> isize; // AVL specific node property // setters for node properties - fn set_height(&self, value: isize); // AVL - fn set_value(&self, value: T); fn set_parent(&mut self, parent: AVLTreeNode); fn set_left(&mut self, left: AVLTreeNode); fn set_right(&mut self, right: AVLTreeNode); + fn set_height(&self, value: isize); // AVL specific node property } + impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + fn print_traversal(&self) { + if self.is_some() && self.value().is_some() { + self.left().print_traversal(); + print!("{:?} ", self.value().unwrap()); + self.right().print_traversal(); + } + } + + fn count_leaves(&self) -> usize { + if self.value().is_none() { + 0 + } else if self.left().value().is_none() && self.right().value().is_none() { + 1 + } else { + self.left().count_leaves() + self.right().count_leaves() + } + } + + fn get_depth_vec(&self) -> Vec> { + let mut vec: Vec> = Vec::new(); + self.calc_depth(0, &mut vec); + vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + vec + } + + fn calc_depth(&self, dep: usize, vec: &mut Vec>) { + match self.value() { + Some(_) => { + vec.push(Depth { + value: self.value(), + depth: dep, + }); + self.left().calc_depth(dep+1, vec); + self.right().calc_depth(dep+1, vec) + } + None => {}, + } + } + + // required getters for node properties + fn value(&self) -> Option { + match self { + Some(tree_node) => tree_node.borrow().value, + None => None + } + } + + // setters for node properties + fn set_value(&self, value: T) { + self.unwrapped().borrow_mut().value = Some(value); + } +} + +impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { fn new(val: T) -> AVLTreeNode { let tree_node = Some(Rc::new(RefCell::new(AVLNode { value: Some(val), @@ -93,24 +146,6 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn print_traversal(&self) { - if self.is_some() && self.value().is_some() { - self.left().print_traversal(); - print!("{:?} ", self.value().unwrap()); - self.right().print_traversal(); - } - } - - fn count_leaves(&self) -> usize { - if self.value().is_none() { - 0 - } else if self.left().value().is_none() && self.right().value().is_none() { - 1 - } else { - self.left().count_leaves() + self.right().count_leaves() - } - } - fn recalc_height(&mut self) { let left = self.left(); let right = self.right(); @@ -132,13 +167,6 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn value(&self) -> Option { - match self { - Some(tree_node) => tree_node.borrow().value, - None => None - } - } - fn parent(&self) -> AVLTreeNode { match self { Some(tree_node) => tree_node.borrow().parent.clone(), @@ -181,36 +209,10 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn get_depth_vec(&self) -> Vec> { - let mut deepy: Vec> = Vec::new(); - self.calc_depth(0, &mut deepy); - deepy.sort_by(|a, b| b.depth.cmp(&a.depth)); - deepy - } - - fn calc_depth(&self, dep: usize, vec: &mut Vec>) { - match self.value() { - Some(_) => { - vec.push(Depth { - value: self.value(), - depth: dep, - }); - self.left().calc_depth(dep+1, vec); - self.right().calc_depth(dep+1, vec) - } - None => {}, - } - } - - fn set_height(&self, value: isize) { self.unwrapped().borrow_mut().height = value; } - fn set_value(&self, value: T) { - self.unwrapped().borrow_mut().value = Some(value); - } - fn set_parent(&mut self, parent: AVLTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().parent = parent, @@ -505,10 +507,4 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D fn get_depth_vec(&self) -> Vec> { self.root.get_depth_vec() } -} - -#[derive(Debug)] -pub struct Depth { - pub value: Option, - pub depth: usize, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ccf8f69..7530e15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ mod tree; use red_black_tree::*; use avl_tree::*; use tests::*; -// use tree::TreeBase; +use crate::tree::*; use std::io::{stdin, stdout, Write}; @@ -180,9 +180,9 @@ fn main() { it_works(); // print_test(); // delete_cases_2_4(); - // test_delete_rbt(); - // avl_test(); - // delete_avl(); + test_delete_rbt(); + avl_test(); + delete_avl(); // benchmark_redblack(); // benchmark_avl(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 1f1a10a..ffa3bcc 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -289,23 +289,23 @@ impl RBTree { } pub trait RBTreeTraits { - fn height(&self) -> usize; - fn is_empty(&self) -> bool; - fn size(&self) -> usize; + // fn height(&self) -> usize; + // fn is_empty(&self) -> bool; + // fn size(&self) -> usize; fn search(&self, value: T) -> RBTreeNode; - fn contains(&self, value: T) -> bool; - fn count_leaves(&self) -> usize; + // fn contains(&self, value: T) -> bool; + // fn count_leaves(&self) -> usize; fn rotate(&mut self, node: &RBTreeNode, direction: bool); fn fix_insert_color(&mut self, node: &RBTreeNode); fn fix_delete_color(&mut self, node: &RBTreeNode); - fn insert_node(&mut self, value: T); - fn delete_node(&mut self, value: T); - fn print(&self); - fn get_depth_vec(&self) -> Vec>; + // fn insert_node(&mut self, value: T); + // fn delete_node(&mut self, value: T); + // fn print(&self); + // fn get_depth_vec(&self) -> Vec>; } -impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { - // TODO ask miller if nil nodes are included +impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { + fn height(&self) -> usize { self.root.node_height() @@ -325,10 +325,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.len } - fn search(&self, value: T) -> RBTreeNode { - self.root.find_node(value) - } - fn contains(&self, value: T) -> bool { match self.search(value) { Some(_) => true, @@ -340,6 +336,124 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.root.count_leaves() } + fn insert_node(&mut self, value: T) { + let mut new_node = RBTreeNode::new(value); + + if self.is_empty() { + self.root = new_node.clone(); + } else if self.search(value).is_some() { + // sticking with printing an err msg because panic causes the terminal to exit the program + println!("Value already exists!"); + return; + } else { + let mut curr_node = self.root.clone(); + let mut curr_node_parent: RBTreeNode = None; + let mut is_left_child = true; + + // find empty node + while curr_node.value().is_some() { + curr_node_parent = curr_node.clone(); + if value < curr_node.value().unwrap() { + curr_node = curr_node.left(); + is_left_child = true; + } else { + curr_node = curr_node.right(); + is_left_child = false; + } + } + + // place new_node in found spot + if curr_node_parent.is_some() { + new_node.set_parent(curr_node_parent); + if is_left_child { + new_node.parent().set_left(new_node.clone()); + } else { + new_node.parent().set_right(new_node.clone()); + } + } else { + panic!("Current node has no parent!"); + } + } + + self.fix_insert_color(&new_node); + self.len += 1; + } + + fn delete_node(&mut self, value: T) { + let mut node = self.search(value); + + if node.is_none() { + println!("Node does not exist!"); + return; + } + + if node.left().value().is_some() && node.right().value().is_some() { + let mut larger = node.left(); + + while larger.right().value().is_some() { // larger.left() + larger = larger.right(); // larger.left() + } + + node.set_value(larger.value().unwrap()); + node = larger.clone(); + } + + // set node to null sibling + let mut child = match node.left().value() { + Some(_) => node.left(), + None => node.right() + }; + + if !node.compare(&self.root) && node.parent().is_some() { + child.set_parent(node.parent()); + if node.compare(&node.parent().left()) { + node.parent().set_left(child.clone()); + } else { + node.parent().set_right(child.clone()); + } + } else if child.is_none() { + // empty tree if child is None + self.root = None; + self.len -= 1; + return; + } else { + // set root to child + self.root = child.clone(); + child.set_parent(None); + } + + if node.is_black() { + if child.is_red() { + child.set_color(NodeColor::Black); + } else { + self.fix_delete_color(&child); + } + } + + self.len -= 1; + } + + fn print(&self) { + if self.is_empty() { + println!("Tree is empty. Nothing to print."); + } else { + println!("Root: {:?}", self.root.value().unwrap()); + self.root.print_traversal(); + println!(); + } + } + + fn get_by_depth(&self) -> Vec> { + self.root.get_depth_vec() + } +} + +impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { + + fn search(&self, value: T) -> RBTreeNode { + self.root.find_node(value) + } + fn rotate(&mut self, node: &RBTreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); @@ -418,49 +532,6 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb grandparent.set_color(NodeColor::Red); } - fn insert_node(&mut self, value: T) { - let mut new_node = RBTreeNode::new(value); - - if self.is_empty() { - self.root = new_node.clone(); - } else if self.search(value).is_some() { - // sticking with printing an err msg because panic causes the terminal to exit the program - println!("Value already exists!"); - return; - } else { - let mut curr_node = self.root.clone(); - let mut curr_node_parent: RBTreeNode = None; - let mut is_left_child = true; - - // find empty node - while curr_node.value().is_some() { - curr_node_parent = curr_node.clone(); - if value < curr_node.value().unwrap() { - curr_node = curr_node.left(); - is_left_child = true; - } else { - curr_node = curr_node.right(); - is_left_child = false; - } - } - - // place new_node in found spot - if curr_node_parent.is_some() { - new_node.set_parent(curr_node_parent); - if is_left_child { - new_node.parent().set_left(new_node.clone()); - } else { - new_node.parent().set_right(new_node.clone()); - } - } else { - panic!("Current node has no parent!"); - } - } - - self.fix_insert_color(&new_node); - self.len += 1; - } - fn fix_delete_color(&mut self, node: &RBTreeNode) { // CASE 1: node is root so done (it’s already black) if node.compare(&self.root) { @@ -528,72 +599,4 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb self.rotate(&sibling, ROTATE_RIGHT); } } - - fn delete_node(&mut self, value: T) { - let mut node = self.search(value); - - if node.is_none() { - println!("Node does not exist!"); - return; - } - - if node.left().value().is_some() && node.right().value().is_some() { - let mut larger = node.left(); - - while larger.right().value().is_some() { // larger.left() - larger = larger.right(); // larger.left() - } - - node.set_value(larger.value().unwrap()); - node = larger.clone(); - } - - // set node to null sibling - let mut child = match node.left().value() { - Some(_) => node.left(), - None => node.right() - }; - - if !node.compare(&self.root) && node.parent().is_some() { - child.set_parent(node.parent()); - if node.compare(&node.parent().left()) { - node.parent().set_left(child.clone()); - } else { - node.parent().set_right(child.clone()); - } - } else if child.is_none() { - // empty tree if child is None - self.root = None; - self.len -= 1; - return; - } else { - // set root to child - self.root = child.clone(); - child.set_parent(None); - } - - if node.is_black() { - if child.is_red() { - child.set_color(NodeColor::Black); - } else { - self.fix_delete_color(&child); - } - } - - self.len -= 1; - } - - fn print(&self) { - if self.is_empty() { - println!("Tree is empty. Nothing to print."); - } else { - println!("Root: {:?}", self.root.value().unwrap()); - self.root.print_traversal(); - println!(); - } - } - - fn get_depth_vec(&self) -> Vec> { - self.root.get_depth_vec() - } } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 04221c3..ec97eb5 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,6 +1,7 @@ use super::*; -use avl_tree::AVLTreeTraits; -use crate::tree::NodeTraits; +use avl_tree::*; +use red_black_tree::*; +use crate::tree::*; // #[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main @@ -13,7 +14,7 @@ pub fn benchmark_redblack() { tree.insert_node(i); } - let depth = tree.get_depth_vec(); + let depth = tree.get_by_depth(); let time = std::time::Instant::now(); for i in 0..tree_size/10 { diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..e69de29 From 3f148e6987cc49ae32996740334d3ea6bea7be1c Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 20:10:38 -0700 Subject: [PATCH 70/80] clean up + add comments --- src/avl_tree.rs | 232 ++++++++++++++++++++++++------------------ src/red_black_tree.rs | 66 +++++++----- src/tests.rs | 2 +- 3 files changed, 175 insertions(+), 125 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index c964479..7fdc897 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -47,6 +47,8 @@ pub trait AVLNodeTraits { impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + + // print in-order traversal of tree fn print_traversal(&self) { if self.is_some() && self.value().is_some() { self.left().print_traversal(); @@ -55,6 +57,7 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } + // count number of leaves in a tree fn count_leaves(&self) -> usize { if self.value().is_none() { 0 @@ -101,6 +104,8 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + + // return new instance of an AVL tree node fn new(val: T) -> AVLTreeNode { let tree_node = Some(Rc::new(RefCell::new(AVLNode { value: Some(val), @@ -111,9 +116,11 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm }))); tree_node.left().set_parent(tree_node.clone()); tree_node.right().set_parent(tree_node.clone()); + tree_node } + // return unwrapped tree node (reference counter) fn unwrapped(&self) -> Rc>> { match self { Some(tree_node) => Rc::clone(&tree_node), @@ -121,6 +128,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // compare if two nodes are the same or not fn compare(&self, node: &AVLTreeNode) -> bool { if self.is_none() || node.is_none() { return false @@ -128,6 +136,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } + // search for a node with given value fn find_node(&self, value: T) -> AVLTreeNode { match self.value() { Some(_) => { @@ -146,19 +155,14 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // relcalculate the height of a node fn recalc_height(&mut self) { let left = self.left(); let right = self.right(); self.set_height(1 + max(left.height(), right.height())); } - fn height(&self) -> isize { - match self { - Some(tree_node) => tree_node.borrow().height, - None => 0 - } - } - + // calculate the balance of a node with respect to its height fn get_balance(&self) -> isize { if self.is_none() { 0 @@ -167,6 +171,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return the parent of a node fn parent(&self) -> AVLTreeNode { match self { Some(tree_node) => tree_node.borrow().parent.clone(), @@ -174,6 +179,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return the left child of a node fn left(&self) -> AVLTreeNode { match self { Some(tree_node) => tree_node.borrow().left.clone(), @@ -181,6 +187,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return the right child of a node fn right(&self) -> AVLTreeNode { match self { Some(tree_node) => tree_node.borrow().right.clone(), @@ -188,10 +195,12 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return the parent of a node's parent fn grandparent(&self) -> AVLTreeNode { self.parent().parent() } + // return a parent node's sibling fn uncle(&self) -> AVLTreeNode { if self.grandparent().left().is_none() || self.grandparent().right().is_none() { None @@ -202,6 +211,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return a node's sibling fn sibling(&self) -> AVLTreeNode { match self.compare(&self.parent().left()) { true => self.parent().right(), @@ -209,10 +219,20 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // return the height of a node + fn height(&self) -> isize { + match self { + Some(tree_node) => tree_node.borrow().height, + None => 0 + } + } + + // set the height of a node fn set_height(&self, value: isize) { self.unwrapped().borrow_mut().height = value; } + // set the parent of a node fn set_parent(&mut self, parent: AVLTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().parent = parent, @@ -226,6 +246,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // set the left child of a node fn set_left(&mut self, left: AVLTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().left = left, @@ -239,6 +260,7 @@ impl AVLNodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fm } } + // set the right child of a node fn set_right(&mut self, right: AVLTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().right = right, @@ -270,37 +292,30 @@ impl AVLTree { } pub trait AVLTreeTraits { - fn height(&self) -> usize; - fn is_empty(&self) -> bool; - fn size(&self) -> usize; + // methods required to be implemented for a fully functional AVL tree fn search(&self, value: T) -> AVLTreeNode; - fn contains(&self, value: T) -> bool; - fn count_leaves(&self) -> usize; fn rotate(&mut self, node: &AVLTreeNode, direction: bool); fn rebalance(&mut self, node: &mut AVLTreeNode); - fn insert_node(&mut self, value: T); - fn delete_node(&mut self, value: T); - fn print(&self); - fn get_depth_vec(&self) -> Vec>; } -impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { +impl TreeBase for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { + + // get the height of a tree fn height(&self) -> usize { self.root.height() as usize } + // check if a tree is empty fn is_empty(&self) -> bool { self.root.is_none() } + // get the size of a tree fn size(&self) -> usize { self.len } - fn search(&self, value: T) -> AVLTreeNode { - self.root.find_node(value) - } - + // check if a tree contains a value fn contains(&self, value: T) -> bool { match self.search(value) { Some(_) => true, @@ -308,89 +323,12 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } } + // count the number of leaves in a tree fn count_leaves(&self) -> usize { self.root.count_leaves() } - fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { - let mut parent = node.parent().clone(); - let mut grandparent = node.grandparent().clone(); - let mut node = node.clone(); - - if parent.compare(&self.root) { - self.root = node.clone(); - } else { - node.set_parent(grandparent.clone()); - if parent.compare(&grandparent.left()) { - grandparent.set_left(node.clone()); - } else { - grandparent.set_right(node.clone()); - } - } - - parent.set_parent(node.clone()); - if direction == ROTATE_LEFT { - if node.left().is_some() { - node.left().set_parent(parent.clone()); - } - parent.set_right(node.left()); - parent.recalc_height(); - node.set_left(parent); - } else { - if node.right().is_some() { - node.right().set_parent(parent.clone()); - } - parent.set_left(node.right()); - parent.recalc_height(); - node.set_right(parent); - } - - node.recalc_height(); - } - - fn rebalance(&mut self, node: &mut AVLTreeNode) { - node.recalc_height(); - let balance = node.get_balance(); - - // Left Cases - if balance > 1 { - // LEFT RIGHT - if node.left().right().height() > node.left().left().height() { - self.rotate(&node.left().right(), ROTATE_LEFT); - self.rotate(&node.left(), ROTATE_RIGHT); - self.root.recalc_height(); - return - } - // LEFT LEFT - else if node.left().right().height() <= node.left().left().height() { - self.rotate(&node.left(), ROTATE_RIGHT); - self.root.recalc_height(); - return; - } - } - - // RIGHT Cases - if balance < -1 { - // RIGHT LEFT - if node.right().left().height() > node.right().right().height() { - self.rotate(&node.right().left(), ROTATE_RIGHT); - self.rotate(&node.right(), ROTATE_LEFT); - self.root.recalc_height(); - return; - } - // RIGHT RIGHT - else if node.right().left().height() <= node.right().right().height() { - self.rotate(&node.right(), ROTATE_LEFT); - self.root.recalc_height(); - return; - } - } - - if node.parent().is_some() && !node.compare(&self.root) { - self.rebalance(&mut node.parent()); - } - } - + // insert a node into a tree fn insert_node(&mut self, value: T) { // REGULAR BINARY SEARCH TREE INSERTION let mut new_node = AVLTreeNode::new(value); @@ -439,6 +377,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D self.len += 1; } + // remove/delete a node from a tree fn delete_node(&mut self, value: T) { let mut node = self.search(value); @@ -494,6 +433,7 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D self.len -= 1; } + // print the in-order traversal in a tree fn print(&self) { if self.is_empty() { println!("Tree is empty. Nothing to print."); @@ -504,7 +444,97 @@ impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::D } } - fn get_depth_vec(&self) -> Vec> { + // return all the values in an AVL tree by depth + fn get_by_depth(&self) -> Vec> { self.root.get_depth_vec() } +} + +impl AVLTreeTraits for AVLTree where T: Copy + PartialOrd + std::fmt::Debug { + + // search for a node with given value in a tree + fn search(&self, value: T) -> AVLTreeNode { + self.root.find_node(value) + } + + // rotate a subtree/node either LEFT or RIGHT + fn rotate(&mut self, node: &AVLTreeNode, direction: bool) { + let mut parent = node.parent().clone(); + let mut grandparent = node.grandparent().clone(); + let mut node = node.clone(); + + if parent.compare(&self.root) { + self.root = node.clone(); + } else { + node.set_parent(grandparent.clone()); + if parent.compare(&grandparent.left()) { + grandparent.set_left(node.clone()); + } else { + grandparent.set_right(node.clone()); + } + } + + parent.set_parent(node.clone()); + if direction == ROTATE_LEFT { + if node.left().is_some() { + node.left().set_parent(parent.clone()); + } + parent.set_right(node.left()); + parent.recalc_height(); + node.set_left(parent); + } else { + if node.right().is_some() { + node.right().set_parent(parent.clone()); + } + parent.set_left(node.right()); + parent.recalc_height(); + node.set_right(parent); + } + + node.recalc_height(); + } + + // rebalance a tree following insertion or deletion + fn rebalance(&mut self, node: &mut AVLTreeNode) { + node.recalc_height(); + let balance = node.get_balance(); + + // Left Cases + if balance > 1 { + // LEFT RIGHT + if node.left().right().height() > node.left().left().height() { + self.rotate(&node.left().right(), ROTATE_LEFT); + self.rotate(&node.left(), ROTATE_RIGHT); + self.root.recalc_height(); + return + } + // LEFT LEFT + else if node.left().right().height() <= node.left().left().height() { + self.rotate(&node.left(), ROTATE_RIGHT); + self.root.recalc_height(); + return; + } + } + + // RIGHT Cases + if balance < -1 { + // RIGHT LEFT + if node.right().left().height() > node.right().right().height() { + self.rotate(&node.right().left(), ROTATE_RIGHT); + self.rotate(&node.right(), ROTATE_LEFT); + self.root.recalc_height(); + return; + } + // RIGHT RIGHT + else if node.right().left().height() <= node.right().right().height() { + self.rotate(&node.right(), ROTATE_LEFT); + self.root.recalc_height(); + return; + } + } + + if node.parent().is_some() && !node.compare(&self.root) { + self.rebalance(&mut node.parent()); + } + } } \ No newline at end of file diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index ffa3bcc..36787b8 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -54,6 +54,8 @@ pub trait RBTNodeTraits { } impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + + // print in-order traversal of tree fn print_traversal(&self) { if self.is_some() && self.value().is_some() { self.left().print_traversal(); @@ -66,6 +68,7 @@ impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::D } } + // count number of leaves in a tree fn count_leaves(&self) -> usize { if self.value().is_none() { 0 @@ -112,6 +115,8 @@ impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::D } impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::Debug { + + // return new instance of a red-black tree node fn new(val: T) -> RBTreeNode { let tree_node = Some(Rc::new(RefCell::new(RBTNode { color: NodeColor::Red, @@ -126,6 +131,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt tree_node } + // return unwrapped tree node (reference counter) fn unwrapped(&self) -> Rc>> { match self { Some(tree_node) => Rc::clone(&tree_node), @@ -133,6 +139,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // compare if two nodes are the same or not fn compare(&self, node: &RBTreeNode) -> bool { if self.is_none() || node.is_none() { return false @@ -140,6 +147,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt Rc::ptr_eq(&self.unwrapped(), &node.unwrapped()) } + // search for a node with given value fn find_node(&self, value: T) -> RBTreeNode { match self.value() { Some(_) => { @@ -155,6 +163,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // get the height of a node fn node_height(&self) -> usize { match self.value() { Some(_) => { @@ -171,21 +180,17 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // determine if a node is red fn is_red(&self) -> bool { self.color() == NodeColor::Red } + // determine if a node is black fn is_black(&self) -> bool { self.color() == NodeColor::Black } - fn color(&self) -> NodeColor { - match self { - Some(tree_node) => tree_node.borrow().color.clone(), - None => NodeColor::Black // nil nodes are black - } - } - + // return the parent of a node fn parent(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().parent.clone(), @@ -193,6 +198,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // return the left child of a node fn left(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().left.clone(), @@ -200,6 +206,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // return the right child of a node fn right(&self) -> RBTreeNode { match self { Some(tree_node) => tree_node.borrow().right.clone(), @@ -207,10 +214,12 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // return the parent of a node's parent fn grandparent(&self) -> RBTreeNode { self.parent().parent() } + // return a parent node's sibling fn uncle(&self) -> RBTreeNode { if self.grandparent().left().is_none() || self.grandparent().right().is_none() { None @@ -221,6 +230,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // return a node's sibling fn sibling(&self) -> RBTreeNode { match self.compare(&self.parent().left()) { true => self.parent().right(), @@ -228,10 +238,20 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // return the color of a node + fn color(&self) -> NodeColor { + match self { + Some(tree_node) => tree_node.borrow().color.clone(), + None => NodeColor::Black // nil nodes are black + } + } + + // set the color of a node fn set_color(&self, color: NodeColor) { self.unwrapped().borrow_mut().color = color; } + // set the parent of a node fn set_parent(&mut self, parent: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().parent = parent, @@ -245,6 +265,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // set the left child of a node fn set_left(&mut self, left: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().left = left, @@ -258,6 +279,7 @@ impl RBTNodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt } } + // set the right child of a node fn set_right(&mut self, right: RBTreeNode) { match self { Some(tree_node) => tree_node.borrow_mut().right = right, @@ -289,42 +311,31 @@ impl RBTree { } pub trait RBTreeTraits { - // fn height(&self) -> usize; - // fn is_empty(&self) -> bool; - // fn size(&self) -> usize; + // methods required to be implemented for a fully functional red-black tree fn search(&self, value: T) -> RBTreeNode; - // fn contains(&self, value: T) -> bool; - // fn count_leaves(&self) -> usize; fn rotate(&mut self, node: &RBTreeNode, direction: bool); fn fix_insert_color(&mut self, node: &RBTreeNode); fn fix_delete_color(&mut self, node: &RBTreeNode); - // fn insert_node(&mut self, value: T); - // fn delete_node(&mut self, value: T); - // fn print(&self); - // fn get_depth_vec(&self) -> Vec>; } impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { + // get the height of a tree fn height(&self) -> usize { self.root.node_height() - - // use code below if nil nodes are included - // if self.len >= 1 { - // self.root.node_height() + 1 - // } else { - // 0 - // } } + // check if a tree is empty fn is_empty(&self) -> bool { self.root.is_none() } + // get the size of a tree fn size(&self) -> usize { self.len } + // check if a tree contains a value fn contains(&self, value: T) -> bool { match self.search(value) { Some(_) => true, @@ -332,10 +343,12 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { } } + // count the number of leaves in a tree fn count_leaves(&self) -> usize { self.root.count_leaves() } + // insert a node into a tree fn insert_node(&mut self, value: T) { let mut new_node = RBTreeNode::new(value); @@ -379,6 +392,7 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { self.len += 1; } + // remove/delete a node from a tree fn delete_node(&mut self, value: T) { let mut node = self.search(value); @@ -433,6 +447,7 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { self.len -= 1; } + // print the in-order traversal in a tree fn print(&self) { if self.is_empty() { println!("Tree is empty. Nothing to print."); @@ -443,6 +458,7 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { } } + // return all the values in a red-black tree by depth fn get_by_depth(&self) -> Vec> { self.root.get_depth_vec() } @@ -450,10 +466,12 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Debug { + // search for a node with given value in a tree fn search(&self, value: T) -> RBTreeNode { self.root.find_node(value) } + // rotate a subtree/node either LEFT or RIGHT fn rotate(&mut self, node: &RBTreeNode, direction: bool) { let mut parent = node.parent().clone(); let mut grandparent = node.grandparent().clone(); @@ -486,6 +504,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb } } + // rebalance a tree by fixing the colors of nodes after inserting a node fn fix_insert_color(&mut self, node: &RBTreeNode) { // CASE 1 if node.compare(&self.root) { @@ -532,6 +551,7 @@ impl RBTreeTraits for RBTree where T: Copy + PartialOrd + std::fmt::Deb grandparent.set_color(NodeColor::Red); } + // rebalance a tree by fixing the colors of nodes after deleting a node fn fix_delete_color(&mut self, node: &RBTreeNode) { // CASE 1: node is root so done (it’s already black) if node.compare(&self.root) { diff --git a/src/tests.rs b/src/tests.rs index ec97eb5..f0e5fdb 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -36,7 +36,7 @@ pub fn benchmark_avl() { tree.insert_node(i); } - let depth = tree.get_depth_vec(); + let depth = tree.get_by_depth(); let time = std::time::Instant::now(); From 0bdda08ff3ebc91d02842dd91a0a614102fee0d3 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 23:12:55 -0700 Subject: [PATCH 71/80] =?UTF-8?q?PAIN=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/avl_tree.rs | 36 ++++++++++++++++++++++++------------ src/main.rs | 42 +++++++++++++++++++++++------------------- src/red_black_tree.rs | 25 +++++++++++++------------ src/tests.rs | 36 +++++++++++++++++++++++++++++++----- src/tree.rs | 14 +++++--------- 5 files changed, 96 insertions(+), 57 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 7fdc897..da7f015 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::rc::Rc; use std::cmp::max; -use crate::tree::{TreeBase, NodeTraits, Depth}; +use crate::tree::{TreeBase, NodeTraits}; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -68,22 +68,34 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - fn get_depth_vec(&self) -> Vec> { - let mut vec: Vec> = Vec::new(); + // fn get_depth_map(&self) -> HashMap { + // let mut map: HashMap = HashMap::new(); + // // self.calc_depth(0, &mut map); + // map + // } + + fn get_depth_vec(&self) -> Vec<(T, usize)> { + let mut vec: Vec<(T, usize)> = Vec::new(); self.calc_depth(0, &mut vec); - vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + // vec.sort_by(|a, b| b.depth.cmp(&a.depth)); vec } - fn calc_depth(&self, dep: usize, vec: &mut Vec>) { + fn calc_depth(&self, depth: usize, vec: &mut Vec<(T, usize)>) { + // match self.value() { + // Some(_) => { + // map.insert(depth, self.value().unwrap()); + // self.left().calc_depth(depth + 1, map); + // self.right().calc_depth(depth + 1, map); + // }, + // None => { }, + // } match self.value() { Some(_) => { - vec.push(Depth { - value: self.value(), - depth: dep, - }); - self.left().calc_depth(dep+1, vec); - self.right().calc_depth(dep+1, vec) + vec.push((self.value().unwrap(), depth)); + + self.left().calc_depth(depth+1, vec); + self.right().calc_depth(depth+1, vec); } None => {}, } @@ -445,7 +457,7 @@ impl TreeBase for AVLTree where T: Copy + PartialOrd + std::fmt::Debug } // return all the values in an AVL tree by depth - fn get_by_depth(&self) -> Vec> { + fn get_by_depth(&self) -> Vec<(T, usize)> { self.root.get_depth_vec() } } diff --git a/src/main.rs b/src/main.rs index 7530e15..804f21f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -151,9 +151,13 @@ fn benchmark_tests() { let choice = get_input(">"); match choice { 1 => { - benchmark_redblack(); + // let mut tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); + // benchmark_insert_search(tree); + benchmark_rbt(); }, 2 => { + // let mut tree: avl_tree::AVLTree = avl_tree::AVLTree::new(); + // benchmark_insert_search(tree); benchmark_avl(); }, 3 => break, @@ -163,26 +167,26 @@ fn benchmark_tests() { } fn main() { - // loop { - // println!("{}", MAIN_MENU); - // let choice = get_input(">"); - // match choice { - // 1 => rbt(), - // 2 => avl(), - // 3 => benchmark_tests(), - // 4 => { - // println!("ok bye"); - // break; - // }, - // _ => println!("Invalid input!") - // } - // } - it_works(); + loop { + println!("{}", MAIN_MENU); + let choice = get_input(">"); + match choice { + 1 => rbt(), + 2 => avl(), + 3 => benchmark_tests(), + 4 => { + println!("ok bye"); + break; + }, + _ => println!("Invalid input!") + } + } + // it_works(); // print_test(); // delete_cases_2_4(); - test_delete_rbt(); - avl_test(); - delete_avl(); + // test_delete_rbt(); + // avl_test(); + // delete_avl(); // benchmark_redblack(); // benchmark_avl(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 36787b8..9fe2931 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; -use crate::tree::{TreeBase, NodeTraits, Depth}; +use crate::tree::{TreeBase, NodeTraits}; static ROTATE_LEFT: bool = true; static ROTATE_RIGHT: bool = false; @@ -79,22 +79,23 @@ impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::D } } - fn get_depth_vec(&self) -> Vec> { - let mut vec: Vec> = Vec::new(); + fn get_depth_vec(&self) -> Vec<(T, usize)> { + let mut vec: Vec<(T, usize)> = Vec::new(); self.calc_depth(0, &mut vec); - vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + vec.sort_by(|a, b| b.1.cmp(&a.1)); vec } - fn calc_depth(&self, dep: usize, vec: &mut Vec>) { + fn calc_depth(&self, depth: usize, vec: &mut Vec<(T, usize)>) { match self.value() { Some(_) => { - vec.push(Depth { - value: self.value(), - depth: dep, - }); - self.left().calc_depth(dep+1, vec); - self.right().calc_depth(dep+1, vec) + let value_in = self.value().unwrap(); + if !vec.iter().any(|x| x.0 == value_in) { + vec.push((self.value().unwrap(), depth)); + } + + self.left().calc_depth(depth+1, vec); + self.right().calc_depth(depth+1, vec) } None => {}, } @@ -459,7 +460,7 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { } // return all the values in a red-black tree by depth - fn get_by_depth(&self) -> Vec> { + fn get_by_depth(&self) -> Vec<(T, usize)> { self.root.get_depth_vec() } } diff --git a/src/tests.rs b/src/tests.rs index f0e5fdb..4525b63 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -5,8 +5,35 @@ use crate::tree::*; // #[cfg(test)] // TODO: write actual tests lmao // moved the stuff here to write the command line interface in main -// #[test] -pub fn benchmark_redblack() { +// // #[test] +// pub fn benchmark_insert_search(mut in_tree: impl TreeBase) { +// // let intree = in_tree; +// let mut benchmarks = vec![10_000, 40_000, 70_000, 100_000, 130_000]; + +// for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { +// let mut tree = in_tree.clone(); // CANT CLONE NEED TO BORROW TREE SOMEHOW WITHOUT IMPL COPY? + +// for i in 0..tree_size { +// tree.insert_node(i); +// } + +// tree.print(); +// let depth = tree.get_by_depth(); +// let time = std::time::Instant::now(); + +// for i in 0..tree_size/10 { +// match tree.contains(depth[i as usize].0) { +// true => { continue; }, +// false => println!("nope"), +// } +// } + +// println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); + +// } +// } + +pub fn benchmark_rbt() { for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { let mut tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); @@ -18,7 +45,7 @@ pub fn benchmark_redblack() { let time = std::time::Instant::now(); for i in 0..tree_size/10 { - match tree.contains(depth[i as usize].value.unwrap()) { + match tree.contains(depth[i as usize].0) { true => { continue; }, false => println!("nope"), } @@ -38,10 +65,9 @@ pub fn benchmark_avl() { let depth = tree.get_by_depth(); let time = std::time::Instant::now(); - for i in 0..tree_size/10 { - match tree.contains(depth[i as usize].value.unwrap()) { + match tree.contains(depth[i as usize].0) { true => { continue; }, false => println!("nope"), } diff --git a/src/tree.rs b/src/tree.rs index d6f1f62..468c992 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,15 +1,11 @@ -#[derive(Debug)] -pub struct Depth { - pub value: Option, - pub depth: usize, -} - pub trait NodeTraits { // required/default helper functions fn print_traversal(&self); fn count_leaves(&self) -> usize; - fn get_depth_vec(&self) -> Vec>; - fn calc_depth(&self, dep: usize, vec: &mut Vec>); + fn get_depth_vec(&self) -> Vec<(T, usize)>; + fn calc_depth(&self, dep: usize, vec: &mut Vec<(T, usize)>); + // fn calc_depth(&self, dep: usize, map: &mut HashMap); + // fn get_depth_map(&self) -> HashMap; // required getters for node properties fn value(&self) -> Option; @@ -27,6 +23,6 @@ pub trait TreeBase { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn get_by_depth(&self) -> Vec>; + fn get_by_depth(&self) -> Vec<(T, usize)>; } From 4c67bb1afb5351d067f93d7674fa95becdf7352a Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 23:20:51 -0700 Subject: [PATCH 72/80] add lib.rs --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..954b9af --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod red_black_tree; +pub mod avl_tree; +pub mod tree; \ No newline at end of file From c6e1cd78714ee511e9fc279b896503356faee651 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 23:47:21 -0700 Subject: [PATCH 73/80] fix rbt benchmark LAG --- src/red_black_tree.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index 9fe2931..e87fb14 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -79,20 +79,23 @@ impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::D } } + // retrieve a vector containing each node in a tree with respective depth fn get_depth_vec(&self) -> Vec<(T, usize)> { let mut vec: Vec<(T, usize)> = Vec::new(); self.calc_depth(0, &mut vec); - vec.sort_by(|a, b| b.1.cmp(&a.1)); + vec.sort_by(|a, b| b.1.cmp(&a.1)); // sort by depth + vec.dedup_by(|a, b| a.0 == b.0); // remove duplicate nodes vec } + // calculate the depth of each node and store them in a given vector fn calc_depth(&self, depth: usize, vec: &mut Vec<(T, usize)>) { match self.value() { Some(_) => { - let value_in = self.value().unwrap(); - if !vec.iter().any(|x| x.0 == value_in) { - vec.push((self.value().unwrap(), depth)); - } + // let value_in = self.value().unwrap(); + // if !vec.iter().any(|x| x.0 == value_in) { + vec.push((self.value().unwrap(), depth)); + // } self.left().calc_depth(depth+1, vec); self.right().calc_depth(depth+1, vec) From 67e647b3a5213a16e7b2d99bfaaaf5c2a7633f5e Mon Sep 17 00:00:00 2001 From: raysarinas Date: Mon, 2 Mar 2020 23:50:15 -0700 Subject: [PATCH 74/80] clean up --- src/avl_tree.rs | 22 +++++----------------- src/red_black_tree.rs | 4 ---- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index da7f015..368cba2 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -68,34 +68,22 @@ impl NodeTraits for AVLTreeNode where T: Copy + PartialOrd + std::fmt:: } } - // fn get_depth_map(&self) -> HashMap { - // let mut map: HashMap = HashMap::new(); - // // self.calc_depth(0, &mut map); - // map - // } - + // retrieve a vector containing each node in a tree with respective depth fn get_depth_vec(&self) -> Vec<(T, usize)> { let mut vec: Vec<(T, usize)> = Vec::new(); self.calc_depth(0, &mut vec); - // vec.sort_by(|a, b| b.depth.cmp(&a.depth)); + vec.sort_by(|a, b| b.1.cmp(&a.1)); // sort by depth + vec.dedup_by(|a, b| a.0 == b.0); // remove duplicate nodes vec } + // calculate the depth of each node and store them in a given vector fn calc_depth(&self, depth: usize, vec: &mut Vec<(T, usize)>) { - // match self.value() { - // Some(_) => { - // map.insert(depth, self.value().unwrap()); - // self.left().calc_depth(depth + 1, map); - // self.right().calc_depth(depth + 1, map); - // }, - // None => { }, - // } match self.value() { Some(_) => { vec.push((self.value().unwrap(), depth)); - self.left().calc_depth(depth+1, vec); - self.right().calc_depth(depth+1, vec); + self.right().calc_depth(depth+1, vec) } None => {}, } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index e87fb14..a586eb6 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -92,11 +92,7 @@ impl NodeTraits for RBTreeNode where T: Copy + PartialOrd + std::fmt::D fn calc_depth(&self, depth: usize, vec: &mut Vec<(T, usize)>) { match self.value() { Some(_) => { - // let value_in = self.value().unwrap(); - // if !vec.iter().any(|x| x.0 == value_in) { vec.push((self.value().unwrap(), depth)); - // } - self.left().calc_depth(depth+1, vec); self.right().calc_depth(depth+1, vec) } From c0a3f9508e2c4566986fd1e7f514f8f79c87b4b7 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Tue, 3 Mar 2020 00:14:19 -0700 Subject: [PATCH 75/80] clean up rbt tests (commented) --- src/tests.rs | 145 ++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index c7b72a1..87421ad 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -77,134 +77,137 @@ pub fn benchmark_avl() { } } -// pub fn it_works() { -// // Test TreeNode -// let treenode: red_black_tree::TreeNode = red_black_tree::TreeNode::new(5); +// pub fn test_treenode() { +// let treenode: red_black_tree::RBTreeNode = red_black_tree::RBTreeNode::new(5); -// println!("{:?}", treenode.value()); -// println!("{:?}", treenode.color()); +// assert_eq!(treenode.value().unwrap(), 5); +// assert_eq!(treenode.color(), NodeColor::Red); // treenode.set_color(red_black_tree::NodeColor::Black); -// println!("{:?}", treenode.color()); +// assert_eq!(treenode.color(), NodeColor::Black); // treenode.set_value(10); -// println!("{:?}", treenode.value()); +// assert_eq!(treenode.value().unwrap(), 10); +// } + +// fn test_count_leaves_rbt() { + +// } + +// fn test_height_rbt() { + +// } + +// fn test_size_rbt() { + +// } -// // Test RBTree -// println!("\n==== Start Testing RBTree Here ====\n"); +// pub fn test_insert_rbt_all_cases() { // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// println!("empty height = {}", rbt.height()); -// println!("no leaves = {}", rbt.count_leaves()); -// println!(); // let mut vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; // for &x in vec_in.iter() { -// println!("Inserting {} ...", x); // rbt.insert_node(x); -// println!("size = {}", rbt.size()); -// rbt.print(); -// println!("height = {}", rbt.height()); -// println!("number of leaves = {}", rbt.count_leaves()); -// println!(); -// } -// vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; -// for &x in vec_in.iter() { -// assert!(rbt.search(x).is_some()); -// assert!(rbt.contains(x) == true); // } -// assert!(rbt.search(10).is_none()); -// assert!(rbt.contains(10) == false); -// println!("\n==== Start Testing DELETE RBTree Here ====\n"); -// let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// let mut vec_in = vec![30, 20, 40, 10, 50]; -// for &x in vec_in.iter() { -// println!("Inserting {} ...", x); -// rbt2.insert_node(x); -// println!("size = {}", rbt2.size()); -// rbt2.print(); -// println!("height = {}", rbt2.height()); -// println!("leaves = {}", rbt2.count_leaves()); -// println!(); -// } +// // println!("\n==== Start Testing DELETE RBTree Here ====\n"); +// // let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// // let mut vec_in = vec![30, 20, 40, 10, 50]; +// // for &x in vec_in.iter() { +// // println!("Inserting {} ...", x); +// // rbt2.insert_node(x); +// // println!("size = {}", rbt2.size()); +// // rbt2.print(); +// // println!("height = {}", rbt2.height()); +// // println!("leaves = {}", rbt2.count_leaves()); +// // println!(); +// // } + +// // vec_in = vec![10, 20, 30]; +// // for &x in vec_in.iter() { +// // println!("Deleting {} ...", x); +// // rbt2.delete_node(x); +// // println!("size = {}", rbt2.size()); +// // rbt2.print(); +// // println!("height = {}", rbt2.height()); +// // println!("num leaves = {}", rbt2.count_leaves()); +// // println!(); +// // } +// } + +// fn test_rbt_search_contains() { +// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// let vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; -// vec_in = vec![10, 20, 30]; // for &x in vec_in.iter() { -// println!("Deleting {} ...", x); -// rbt2.delete_node(x); -// println!("size = {}", rbt2.size()); -// rbt2.print(); -// println!("height = {}", rbt2.height()); -// println!("num leaves = {}", rbt2.count_leaves()); -// println!(); +// assert!(rbt.search(x).is_some()); +// assert!(rbt.contains(x)); // } + +// assert!(rbt.search(10).is_none()); +// assert!(!rbt.contains(10)); // } -// pub fn test_delete_rbt() { +// fn test_delete_rbt_all() { // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// assert!(rbt.is_empty() == true); + // for x in 1..=10 { // rbt.insert_node(x); -// println!("inserting ... {}", x); +// assert!(rbt.contains(x)); // } // assert!(rbt.is_empty() == false); // rbt.print(); -// println!("deleting everything .."); - // let mut vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; // for &x in vec_in.iter() { -// println!("deleting {} ...", x); // rbt.delete_node(x); +// assert!(!rbt.contains(x)); // } + // assert!(rbt.is_empty() == true); -// rbt.print(); // } -// pub fn delete_cases_1_3_5_6() { + +// pub fn test_delete_rbt_cases_1_3_5_6() { // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +// assert!(rbt.is_empty()); // for x in 1..=10 { // rbt.insert_node(x); -// println!("inserting ... {}", x); +// assert!(rbt.contains(x)); // } +// assert!(!rbt.is_empty()); // let mut vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; // for &x in vec_in.iter() { -// println!("deleting ... {}", x); // rbt.delete_node(x); -// rbt.print(); +// assert!(!rbt.contains(x)); // } +// assert!(!rbt.is_empty()); // } -// pub fn delete_cases_2_4() { -// println!("\n==== Start Testing DELETE RBTree Here ====\n"); +// pub fn test_delete_rbt_cases_2_4() { // let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); // let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; +// assert!(rbt.is_empty()); // for &x in vec_in.iter() { -// println!("inserting {} ...", x); // rbt.insert_node(x); -// println!("size is now = {}", rbt.size()); -// rbt.print(); -// println!("height = {}", rbt.height()); -// println!("leaves = {}", rbt.count_leaves()); -// println!(); +// assert!(rbt.contains(x)); // } +// assert!(!rbt.is_empty()); -// vec_in = vec![17, 84, 99, 5, 1, 60]; -// for &x in vec_in.iter() { -// println!("deleting {} ...", x); +// let to_delete = vec![17, 84, 99, 5, 1, 60]; +// for &x in to_delete.iter() { // rbt.delete_node(x); -// println!("size is now = {}", rbt.size()); -// rbt.print(); -// println!("height = {}", rbt.height()); -// println!("leaves = {}", rbt.count_leaves()); -// println!(); +// assert!(!rbt.contains(x)); // } +// assert!(!rbt.is_empty()); // } // pub fn avl_test() { From b4d0ccea0b60b9bfdaa89bd9e7045f4bde808782 Mon Sep 17 00:00:00 2001 From: Trishia Gatilogo Date: Tue, 3 Mar 2020 11:44:52 -0700 Subject: [PATCH 76/80] clean up --- src/avl_tree.rs | 7 +- src/main.rs | 14 +- src/red_black_tree.rs | 2 +- src/tests.rs | 372 +++++++++++++++++++++--------------------- src/tree.rs | 4 +- 5 files changed, 198 insertions(+), 201 deletions(-) diff --git a/src/avl_tree.rs b/src/avl_tree.rs index 368cba2..be340e3 100644 --- a/src/avl_tree.rs +++ b/src/avl_tree.rs @@ -29,7 +29,6 @@ pub trait AVLNodeTraits { fn get_balance(&self) -> isize; // getters for node properties and family members - fn parent(&self) -> AVLTreeNode; fn left(&self) -> AVLTreeNode; fn right(&self) -> AVLTreeNode; @@ -397,8 +396,8 @@ impl TreeBase for AVLTree where T: Copy + PartialOrd + std::fmt::Debug if node.left().value().is_some() && node.right().value().is_some() { let mut larger = node.left(); - while larger.right().value().is_some() { // larger.left() - larger = larger.right(); // larger.left() + while larger.right().value().is_some() { + larger = larger.right(); } node.set_value(larger.value().unwrap()); @@ -445,7 +444,7 @@ impl TreeBase for AVLTree where T: Copy + PartialOrd + std::fmt::Debug } // return all the values in an AVL tree by depth - fn get_by_depth(&self) -> Vec<(T, usize)> { + fn get_depth_vec(&self) -> Vec<(T, usize)> { self.root.get_depth_vec() } } diff --git a/src/main.rs b/src/main.rs index 4f1e83d..83c0905 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,10 @@ fn get_input(prompt: &str) -> u32 { match value.trim().parse::() { Ok(num) => return num, - Err(_) => continue + Err(_) => { + println!("Invalid input! Please enter a numerical value."); + continue; + } } } } @@ -103,7 +106,6 @@ fn avl() { } fn rbt() { - // not sure what to use for type let mut rbt: RBTree = RBTree::new(); loop { println!("{}", RBT_MENU); @@ -173,12 +175,4 @@ fn main() { _ => println!("Invalid input!") } } - // it_works(); - // print_test(); - // delete_cases_2_4(); - // test_delete_rbt(); - // avl_test(); - // delete_avl(); - // benchmark_redblack(); - // benchmark_avl(); } diff --git a/src/red_black_tree.rs b/src/red_black_tree.rs index a586eb6..c1458a3 100644 --- a/src/red_black_tree.rs +++ b/src/red_black_tree.rs @@ -459,7 +459,7 @@ impl TreeBase for RBTree where T: Copy + PartialOrd + std::fmt::Debug { } // return all the values in a red-black tree by depth - fn get_by_depth(&self) -> Vec<(T, usize)> { + fn get_depth_vec(&self) -> Vec<(T, usize)> { self.root.get_depth_vec() } } diff --git a/src/tests.rs b/src/tests.rs index 87421ad..5aa1346 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,37 +1,5 @@ use super::*; -use avl_tree::*; -use red_black_tree::*; use crate::tree::*; -// #[cfg(test)] -// TODO: write actual tests lmao -// moved the stuff here to write the command line interface in main -// // #[test] -// pub fn benchmark_insert_search(mut in_tree: impl TreeBase) { -// // let intree = in_tree; -// let mut benchmarks = vec![10_000, 40_000, 70_000, 100_000, 130_000]; - -// for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { -// let mut tree = in_tree.clone(); // CANT CLONE NEED TO BORROW TREE SOMEHOW WITHOUT IMPL COPY? - -// for i in 0..tree_size { -// tree.insert_node(i); -// } - -// tree.print(); -// let depth = tree.get_by_depth(); -// let time = std::time::Instant::now(); - -// for i in 0..tree_size/10 { -// match tree.contains(depth[i as usize].0) { -// true => { continue; }, -// false => println!("nope"), -// } -// } - -// println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); - -// } -// } pub fn benchmark_redblack() { for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { @@ -41,7 +9,7 @@ pub fn benchmark_redblack() { tree.insert_node(i); } - let depth = tree.get_by_depth(); + let depth = tree.get_depth_vec(); let time = std::time::Instant::now(); for i in 0..tree_size/10 { @@ -63,7 +31,7 @@ pub fn benchmark_avl() { tree.insert_node(i); } - let depth = tree.get_by_depth(); + let depth = tree.get_depth_vec(); let time = std::time::Instant::now(); for i in 0..tree_size/10 { @@ -77,186 +45,224 @@ pub fn benchmark_avl() { } } -// pub fn test_treenode() { -// let treenode: red_black_tree::RBTreeNode = red_black_tree::RBTreeNode::new(5); - -// assert_eq!(treenode.value().unwrap(), 5); -// assert_eq!(treenode.color(), NodeColor::Red); +// // #[test] +// pub fn benchmark_insert_search(mut in_tree: impl TreeBase) { +// // let intree = in_tree; +// let mut benchmarks = vec![10_000, 40_000, 70_000, 100_000, 130_000]; -// treenode.set_color(red_black_tree::NodeColor::Black); -// assert_eq!(treenode.color(), NodeColor::Black); +// for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { +// let mut tree = in_tree.clone(); // CANT CLONE NEED TO BORROW TREE SOMEHOW WITHOUT IMPL COPY? -// treenode.set_value(10); -// assert_eq!(treenode.value().unwrap(), 10); +// for i in 0..tree_size { +// tree.insert_node(i); +// } -// } +// tree.print(); +// let depth = tree.get_by_depth(); +// let time = std::time::Instant::now(); + +// for i in 0..tree_size/10 { +// match tree.contains(depth[i as usize].0) { +// true => { continue; }, +// false => println!("nope"), +// } +// } -// fn test_count_leaves_rbt() { +// println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); +// } // } -// fn test_height_rbt() { +#[test] +pub fn test_treenode() { + let treenode: red_black_tree::RBTreeNode = red_black_tree::RBTreeNode::new(5); + + assert_eq!(treenode.value().unwrap(), 5); + assert_eq!(treenode.color(), NodeColor::Red); -// } + treenode.set_color(red_black_tree::NodeColor::Black); + assert_eq!(treenode.color(), NodeColor::Black); -// fn test_size_rbt() { + treenode.set_value(10); + assert_eq!(treenode.value().unwrap(), 10); +} -// } +#[test] +fn test_count_leaves_rbt() { -// pub fn test_insert_rbt_all_cases() { -// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +} -// let mut vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; -// for &x in vec_in.iter() { -// rbt.insert_node(x); -// } +#[test] +fn test_height_rbt() { -// // println!("\n==== Start Testing DELETE RBTree Here ====\n"); -// // let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// // let mut vec_in = vec![30, 20, 40, 10, 50]; -// // for &x in vec_in.iter() { -// // println!("Inserting {} ...", x); -// // rbt2.insert_node(x); -// // println!("size = {}", rbt2.size()); -// // rbt2.print(); -// // println!("height = {}", rbt2.height()); -// // println!("leaves = {}", rbt2.count_leaves()); -// // println!(); -// // } - -// // vec_in = vec![10, 20, 30]; -// // for &x in vec_in.iter() { -// // println!("Deleting {} ...", x); -// // rbt2.delete_node(x); -// // println!("size = {}", rbt2.size()); -// // rbt2.print(); -// // println!("height = {}", rbt2.height()); -// // println!("num leaves = {}", rbt2.count_leaves()); -// // println!(); -// // } -// } +} -// fn test_rbt_search_contains() { -// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// let vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; +#[test] +fn test_size_rbt() { -// for &x in vec_in.iter() { -// assert!(rbt.search(x).is_some()); -// assert!(rbt.contains(x)); -// } +} -// assert!(rbt.search(10).is_none()); -// assert!(!rbt.contains(10)); -// } +#[test] +pub fn test_insert_rbt_all_cases() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// fn test_delete_rbt_all() { -// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; + for &x in vec_in.iter() { + rbt.insert_node(x); + } -// assert!(rbt.is_empty() == true); + println!("\n==== Start Testing DELETE RBTree Here ====\n"); + let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let mut vec_in = vec![30, 20, 40, 10, 50]; + for &x in vec_in.iter() { + println!("Inserting {} ...", x); + rbt2.insert_node(x); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("leaves = {}", rbt2.count_leaves()); + println!(); + } -// for x in 1..=10 { -// rbt.insert_node(x); -// assert!(rbt.contains(x)); -// } + vec_in = vec![10, 20, 30]; + for &x in vec_in.iter() { + println!("Deleting {} ...", x); + rbt2.delete_node(x); + println!("size = {}", rbt2.size()); + rbt2.print(); + println!("height = {}", rbt2.height()); + println!("num leaves = {}", rbt2.count_leaves()); + println!(); + } +} -// assert!(rbt.is_empty() == false); -// rbt.print(); +#[test] +fn test_rbt_search_contains() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let vec_in = vec![35, 5, 1, 8, 17, 60, 70, 84, 100, 120]; -// let mut vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; -// for &x in vec_in.iter() { -// rbt.delete_node(x); -// assert!(!rbt.contains(x)); -// } + for &x in vec_in.iter() { + rbt.insert_node(x); + assert!(rbt.search(x).is_some()); + assert!(rbt.contains(x)); + } -// assert!(rbt.is_empty() == true); -// } + assert!(rbt.search(10).is_none()); + assert!(!rbt.contains(10)); +} + +#[test] +fn test_delete_rbt_all() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + assert!(rbt.is_empty() == true); + + for x in 1..=10 { + rbt.insert_node(x); + assert!(rbt.contains(x)); + } + + assert!(rbt.is_empty() == false); + rbt.print(); + let vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; + for &x in vec_in.iter() { + rbt.delete_node(x); + assert!(!rbt.contains(x)); + } + + assert!(rbt.is_empty() == true); +} -// pub fn test_delete_rbt_cases_1_3_5_6() { -// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); +#[test] +pub fn test_delete_rbt_cases_1_3_5_6() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// assert!(rbt.is_empty()); -// for x in 1..=10 { -// rbt.insert_node(x); -// assert!(rbt.contains(x)); -// } -// assert!(!rbt.is_empty()); + assert!(rbt.is_empty()); + for x in 1..=10 { + rbt.insert_node(x); + assert!(rbt.contains(x)); + } + assert!(!rbt.is_empty()); -// let mut vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; -// for &x in vec_in.iter() { -// rbt.delete_node(x); -// assert!(!rbt.contains(x)); -// } -// assert!(!rbt.is_empty()); -// } + let vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; + for &x in vec_in.iter() { + rbt.delete_node(x); + assert!(!rbt.contains(x)); + } + assert!(!rbt.is_empty()); +} -// pub fn test_delete_rbt_cases_2_4() { +#[test] +pub fn test_delete_rbt_cases_2_4() { -// let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); -// let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + let vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; -// assert!(rbt.is_empty()); -// for &x in vec_in.iter() { -// rbt.insert_node(x); -// assert!(rbt.contains(x)); -// } -// assert!(!rbt.is_empty()); + assert!(rbt.is_empty()); + for &x in vec_in.iter() { + rbt.insert_node(x); + assert!(rbt.contains(x)); + } + assert!(!rbt.is_empty()); -// let to_delete = vec![17, 84, 99, 5, 1, 60]; -// for &x in to_delete.iter() { -// rbt.delete_node(x); -// assert!(!rbt.contains(x)); -// } -// assert!(!rbt.is_empty()); -// } + let to_delete = vec![17, 84, 99, 5, 1, 60]; + for &x in to_delete.iter() { + rbt.delete_node(x); + assert!(!rbt.contains(x)); + } + assert!(!rbt.is_empty()); +} -// pub fn avl_test() { -// println!("\n==== Start Testing AVLTree Here ====\n"); - -// let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); -// let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; -// for &x in vec_in.iter() { -// println!("inserting {} ...", x); -// avl.insert_node(x); -// println!("size is now = {}", avl.size()); -// avl.print(); -// println!("height = {}", avl.height()); -// println!("leaves = {}", avl.count_leaves()); -// println!(); -// } +#[test] +pub fn avl_test() { + println!("\n==== Start Testing AVLTree Here ====\n"); + + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); + let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + for &x in vec_in.iter() { + println!("inserting {} ...", x); + avl.insert_node(x); + println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + } -// vec_in = vec![17, 84, 99, 5, 1, 60]; -// for &x in vec_in.iter() { -// println!("deleting {} ...", x); -// avl.delete_node(x); -// println!("size is now = {}", avl.size()); -// avl.print(); -// println!("height = {}", avl.height()); -// println!("leaves = {}", avl.count_leaves()); -// println!(); -// } -// } + vec_in = vec![17, 84, 99, 5, 1, 60]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + avl.delete_node(x); + println!("size is now = {}", avl.size()); + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!(); + } +} -// pub fn delete_avl() { -// let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); +#[test] +pub fn delete_avl() { + let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); -// for x in 1..=10 { -// avl.insert_node(x); -// println!("inserting ... {}", x); -// } -// avl.print(); -// println!("height = {}", avl.height()); -// println!("leaves = {}", avl.count_leaves()); -// println!("=========================="); - -// let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; -// for &x in vec_in.iter() { -// println!("deleting {} ...", x); -// avl.delete_node(x); -// println!("height = {}", avl.height()); -// println!("leaves = {}", avl.count_leaves()); -// avl.print(); -// println!("=========================="); -// } -// println!(); -// } \ No newline at end of file + for x in 1..=10 { + avl.insert_node(x); + println!("inserting ... {}", x); + } + avl.print(); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + println!("=========================="); + + let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; + for &x in vec_in.iter() { + println!("deleting {} ...", x); + avl.delete_node(x); + println!("height = {}", avl.height()); + println!("leaves = {}", avl.count_leaves()); + avl.print(); + println!("=========================="); + } + println!(); +} \ No newline at end of file diff --git a/src/tree.rs b/src/tree.rs index 468c992..9c912d2 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -4,8 +4,6 @@ pub trait NodeTraits { fn count_leaves(&self) -> usize; fn get_depth_vec(&self) -> Vec<(T, usize)>; fn calc_depth(&self, dep: usize, vec: &mut Vec<(T, usize)>); - // fn calc_depth(&self, dep: usize, map: &mut HashMap); - // fn get_depth_map(&self) -> HashMap; // required getters for node properties fn value(&self) -> Option; @@ -23,6 +21,6 @@ pub trait TreeBase { fn insert_node(&mut self, value: T); fn delete_node(&mut self, value: T); fn print(&self); - fn get_by_depth(&self) -> Vec<(T, usize)>; + fn get_depth_vec(&self) -> Vec<(T, usize)>; } From dfc422fda43a93af01808722423ca96ff242e82b Mon Sep 17 00:00:00 2001 From: raysarinas Date: Tue, 3 Mar 2020 12:48:03 -0700 Subject: [PATCH 77/80] clean benchmarks --- src/main.rs | 14 ++++++++++-- src/tests.rs | 63 ++++++---------------------------------------------- 2 files changed, 19 insertions(+), 58 deletions(-) diff --git a/src/main.rs b/src/main.rs index 83c0905..3efb9af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,8 +152,18 @@ fn benchmark_tests() { println!("{}", BENCHMARK_MENU); let choice = get_input(">"); match choice { - 1 => benchmark_redblack(), - 2 => benchmark_avl(), + 1 => { + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); + benchmark_insert_search(tree, tree_size); + } + }, + 2 => { + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let tree: avl_tree::AVLTree = avl_tree::AVLTree::new(); + benchmark_insert_search(tree, tree_size); + } + }, 3 => break, _ => println!("Invalid input!") } diff --git a/src/tests.rs b/src/tests.rs index 5aa1346..b3d41bb 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,78 +1,29 @@ +#[allow(unused_imports)] use super::*; use crate::tree::*; -pub fn benchmark_redblack() { - for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { - let mut tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); +pub fn benchmark_insert_search(in_tree: impl TreeBase, tree_size: u32) { - for i in 0..tree_size { - tree.insert_node(i); - } - - let depth = tree.get_depth_vec(); + let mut tree = in_tree; + let time = std::time::Instant::now(); - - for i in 0..tree_size/10 { - match tree.contains(depth[i as usize].0) { - true => { continue; }, - false => println!("nope"), - } - } - - println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); - } -} - -pub fn benchmark_avl() { - for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { - let mut tree: avl_tree::AVLTree = avl_tree::AVLTree::new(); - for i in 0..tree_size { tree.insert_node(i); } - let depth = tree.get_depth_vec(); - let time = std::time::Instant::now(); + // tree.print(); + // let depth = tree.get_by_depth(); for i in 0..tree_size/10 { - match tree.contains(depth[i as usize].0) { + match tree.contains(i) { true => { continue; }, false => println!("nope"), } } println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); - } } -// // #[test] -// pub fn benchmark_insert_search(mut in_tree: impl TreeBase) { -// // let intree = in_tree; -// let mut benchmarks = vec![10_000, 40_000, 70_000, 100_000, 130_000]; - -// for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { -// let mut tree = in_tree.clone(); // CANT CLONE NEED TO BORROW TREE SOMEHOW WITHOUT IMPL COPY? - -// for i in 0..tree_size { -// tree.insert_node(i); -// } - -// tree.print(); -// let depth = tree.get_by_depth(); -// let time = std::time::Instant::now(); - -// for i in 0..tree_size/10 { -// match tree.contains(depth[i as usize].0) { -// true => { continue; }, -// false => println!("nope"), -// } -// } - -// println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); - -// } -// } - #[test] pub fn test_treenode() { let treenode: red_black_tree::RBTreeNode = red_black_tree::RBTreeNode::new(5); From 422d23c45e30a977d5b3ae0a612b7b6700deb9b1 Mon Sep 17 00:00:00 2001 From: raysarinas Date: Tue, 3 Mar 2020 13:16:12 -0700 Subject: [PATCH 78/80] done deepest --- src/tests.rs | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index b3d41bb..341fcd9 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -11,9 +11,6 @@ pub fn benchmark_insert_search(in_tree: impl TreeBase, tree_size: u32) { tree.insert_node(i); } - // tree.print(); - // let depth = tree.get_by_depth(); - for i in 0..tree_size/10 { match tree.contains(i) { true => { continue; }, @@ -21,7 +18,44 @@ pub fn benchmark_insert_search(in_tree: impl TreeBase, tree_size: u32) { } } - println!("Elapsed time for {}: {} ms", tree_size, time.elapsed().as_millis()); + println!("Elapsed time for tree size of {}: {} ms", tree_size, time.elapsed().as_millis()); +} + +#[allow(dead_code)] +pub fn insert_search_deepest(in_tree: impl TreeBase, tree_size: u32) { + + let mut tree = in_tree; + + let time = std::time::Instant::now(); + for i in 0..tree_size { + tree.insert_node(i); + } + + let depth = tree.get_depth_vec(); + + for i in 0..tree_size/10 { + match tree.contains(depth[i as usize].0) { + true => { continue; }, + false => println!("nope"), + } + } + + println!("Elapsed time for tree size of {}: {} ms", tree_size, time.elapsed().as_millis()); +} + + +#[test] +pub fn benchmark_insert_search_deepest_nodes() { + + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let tree: red_black_tree::RBTree = red_black_tree::RBTree::new(); + insert_search_deepest(tree, tree_size); + } + + for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { + let tree: avl_tree::AVLTree = avl_tree::AVLTree::new(); + insert_search_deepest(tree, tree_size); + } } #[test] From 50ff77df93daf6da6a925297da2bce0c7a9095c6 Mon Sep 17 00:00:00 2001 From: Jacob Wong Date: Tue, 3 Mar 2020 13:21:15 -0700 Subject: [PATCH 79/80] for dessert, we have assert --- src/tests.rs | 66 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index 341fcd9..44e7f29 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -72,21 +72,6 @@ pub fn test_treenode() { assert_eq!(treenode.value().unwrap(), 10); } -#[test] -fn test_count_leaves_rbt() { - -} - -#[test] -fn test_height_rbt() { - -} - -#[test] -fn test_size_rbt() { - -} - #[test] pub fn test_insert_rbt_all_cases() { let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); @@ -96,6 +81,9 @@ pub fn test_insert_rbt_all_cases() { rbt.insert_node(x); } + assert_eq!(rbt.height(), 4); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); println!("\n==== Start Testing DELETE RBTree Here ====\n"); let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); let mut vec_in = vec![30, 20, 40, 10, 50]; @@ -109,6 +97,10 @@ pub fn test_insert_rbt_all_cases() { println!(); } + assert_eq!(rbt2.height(), 3); + assert_eq!(rbt2.size(), 5); + assert_eq!(rbt2.count_leaves(), 2); + vec_in = vec![10, 20, 30]; for &x in vec_in.iter() { println!("Deleting {} ...", x); @@ -119,6 +111,10 @@ pub fn test_insert_rbt_all_cases() { println!("num leaves = {}", rbt2.count_leaves()); println!(); } + + assert_eq!(rbt2.height(), 2); + assert_eq!(rbt2.size(), 2); + assert_eq!(rbt2.count_leaves(), 1); } #[test] @@ -132,6 +128,10 @@ fn test_rbt_search_contains() { assert!(rbt.contains(x)); } + assert_eq!(rbt.height(), 5); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); + assert!(rbt.search(10).is_none()); assert!(!rbt.contains(10)); } @@ -148,6 +148,9 @@ fn test_delete_rbt_all() { } assert!(rbt.is_empty() == false); + assert_eq!(rbt.height(), 5); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); rbt.print(); let vec_in = vec![6, 4, 2, 8, 9, 7, 3, 1, 5, 10]; @@ -157,6 +160,9 @@ fn test_delete_rbt_all() { } assert!(rbt.is_empty() == true); + assert_eq!(rbt.height(), 0); + assert_eq!(rbt.size(), 0); + assert_eq!(rbt.count_leaves(), 0); } #[test] @@ -169,6 +175,9 @@ pub fn test_delete_rbt_cases_1_3_5_6() { assert!(rbt.contains(x)); } assert!(!rbt.is_empty()); + assert_eq!(rbt.height(), 5); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); let vec_in: Vec = vec![4, 6, 8, 1, 5, 9, 2]; for &x in vec_in.iter() { @@ -176,6 +185,9 @@ pub fn test_delete_rbt_cases_1_3_5_6() { assert!(!rbt.contains(x)); } assert!(!rbt.is_empty()); + assert_eq!(rbt.height(), 2); + assert_eq!(rbt.size(), 3); + assert_eq!(rbt.count_leaves(), 2); } #[test] @@ -190,6 +202,9 @@ pub fn test_delete_rbt_cases_2_4() { assert!(rbt.contains(x)); } assert!(!rbt.is_empty()); + assert_eq!(rbt.height(), 4); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); let to_delete = vec![17, 84, 99, 5, 1, 60]; for &x in to_delete.iter() { @@ -197,6 +212,9 @@ pub fn test_delete_rbt_cases_2_4() { assert!(!rbt.contains(x)); } assert!(!rbt.is_empty()); + assert_eq!(rbt.height(), 3); + assert_eq!(rbt.size(), 4); + assert_eq!(rbt.count_leaves(), 2); } #[test] @@ -214,7 +232,11 @@ pub fn avl_test() { println!("leaves = {}", avl.count_leaves()); println!(); } - + + assert_eq!(avl.height(), 4); + assert_eq!(avl.size(), 10); + assert_eq!(avl.count_leaves(), 5); + vec_in = vec![17, 84, 99, 5, 1, 60]; for &x in vec_in.iter() { println!("deleting {} ...", x); @@ -225,6 +247,10 @@ pub fn avl_test() { println!("leaves = {}", avl.count_leaves()); println!(); } + + assert_eq!(avl.height(), 3); + assert_eq!(avl.size(), 4); + assert_eq!(avl.count_leaves(), 2); } #[test] @@ -240,6 +266,10 @@ pub fn delete_avl() { println!("leaves = {}", avl.count_leaves()); println!("=========================="); + assert_eq!(avl.height(), 4); + assert_eq!(avl.size(), 10); + assert_eq!(avl.count_leaves(), 5); + let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; for &x in vec_in.iter() { println!("deleting {} ...", x); @@ -249,5 +279,9 @@ pub fn delete_avl() { avl.print(); println!("=========================="); } + + assert_eq!(avl.height(), 0); + assert_eq!(avl.size(), 0); + assert_eq!(avl.count_leaves(), 0); println!(); } \ No newline at end of file From 3c9f83c17c6cae7de01e41493c95e137f64a0c4a Mon Sep 17 00:00:00 2001 From: raysarinas Date: Tue, 3 Mar 2020 13:26:44 -0700 Subject: [PATCH 80/80] testy vibes --- src/tests.rs | 78 ++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 51 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index 44e7f29..9907826 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -30,7 +30,7 @@ pub fn insert_search_deepest(in_tree: impl TreeBase, tree_size: u32) { for i in 0..tree_size { tree.insert_node(i); } - + let depth = tree.get_depth_vec(); for i in 0..tree_size/10 { @@ -45,6 +45,7 @@ pub fn insert_search_deepest(in_tree: impl TreeBase, tree_size: u32) { #[test] +#[ignore] pub fn benchmark_insert_search_deepest_nodes() { for tree_size in vec![10_000, 40_000, 70_000, 100_000, 130_000] { @@ -73,28 +74,12 @@ pub fn test_treenode() { } #[test] -pub fn test_insert_rbt_all_cases() { - let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); - - let vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; - for &x in vec_in.iter() { - rbt.insert_node(x); - } - - assert_eq!(rbt.height(), 4); - assert_eq!(rbt.size(), 10); - assert_eq!(rbt.count_leaves(), 5); - println!("\n==== Start Testing DELETE RBTree Here ====\n"); +pub fn test_insert_delete_rbt() { let mut rbt2: red_black_tree::RBTree = red_black_tree::RBTree::new(); let mut vec_in = vec![30, 20, 40, 10, 50]; for &x in vec_in.iter() { - println!("Inserting {} ...", x); rbt2.insert_node(x); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("leaves = {}", rbt2.count_leaves()); - println!(); + assert!(rbt2.contains(x)); } assert_eq!(rbt2.height(), 3); @@ -103,13 +88,8 @@ pub fn test_insert_rbt_all_cases() { vec_in = vec![10, 20, 30]; for &x in vec_in.iter() { - println!("Deleting {} ...", x); rbt2.delete_node(x); - println!("size = {}", rbt2.size()); - rbt2.print(); - println!("height = {}", rbt2.height()); - println!("num leaves = {}", rbt2.count_leaves()); - println!(); + assert!(!rbt2.contains(x)); } assert_eq!(rbt2.height(), 2); @@ -117,6 +97,21 @@ pub fn test_insert_rbt_all_cases() { assert_eq!(rbt2.count_leaves(), 1); } +#[test] +pub fn test_insert_rbt_all_cases() { + let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); + + let vec_in = vec![5, 70, 35, 8, 100, 60, 120, 1, 84, 17]; + for &x in vec_in.iter() { + rbt.insert_node(x); + } + + assert_eq!(rbt.height(), 4); + assert_eq!(rbt.size(), 10); + assert_eq!(rbt.count_leaves(), 5); + +} + #[test] fn test_rbt_search_contains() { let mut rbt: red_black_tree::RBTree = red_black_tree::RBTree::new(); @@ -218,19 +213,14 @@ pub fn test_delete_rbt_cases_2_4() { } #[test] -pub fn avl_test() { - println!("\n==== Start Testing AVLTree Here ====\n"); +pub fn avl_test_insert_delete_some() { let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); let mut vec_in: Vec = vec![5, 70, 35, 8, 98, 60, 99, 99, 1, 84, 17]; + for &x in vec_in.iter() { - println!("inserting {} ...", x); avl.insert_node(x); - println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); + assert!(avl.contains(x)); } assert_eq!(avl.height(), 4); @@ -239,13 +229,8 @@ pub fn avl_test() { vec_in = vec![17, 84, 99, 5, 1, 60]; for &x in vec_in.iter() { - println!("deleting {} ...", x); avl.delete_node(x); - println!("size is now = {}", avl.size()); - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!(); + assert!(!avl.contains(x)); } assert_eq!(avl.height(), 3); @@ -254,17 +239,13 @@ pub fn avl_test() { } #[test] -pub fn delete_avl() { +pub fn delete_all_avl() { let mut avl: avl_tree::AVLTree = avl_tree::AVLTree::new(); for x in 1..=10 { avl.insert_node(x); - println!("inserting ... {}", x); + assert!(avl.contains(x)); } - avl.print(); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - println!("=========================="); assert_eq!(avl.height(), 4); assert_eq!(avl.size(), 10); @@ -272,16 +253,11 @@ pub fn delete_avl() { let vec_in = vec![4, 5, 8, 7, 3, 2, 1, 9, 6, 10]; for &x in vec_in.iter() { - println!("deleting {} ...", x); avl.delete_node(x); - println!("height = {}", avl.height()); - println!("leaves = {}", avl.count_leaves()); - avl.print(); - println!("=========================="); + assert!(!avl.contains(x)); } assert_eq!(avl.height(), 0); assert_eq!(avl.size(), 0); assert_eq!(avl.count_leaves(), 0); - println!(); } \ No newline at end of file