From 20ccfdecd4d73c932668700a7c2b8b3e48e3b206 Mon Sep 17 00:00:00 2001 From: Nif Ward Date: Mon, 6 Jan 2014 21:19:36 -0500 Subject: [PATCH] Added in Clone/TotalEq/TotalOrd/ToStr traits to all parts of btree. Equals is now compact and uses vec's equals method. Cmp compares all elements on branches and leaves (Nodes). --- src/libextra/btree.rs | 381 +++++++++++++++++++++++++++++------------- 1 file changed, 261 insertions(+), 120 deletions(-) diff --git a/src/libextra/btree.rs b/src/libextra/btree.rs index 0f9eba2e9dc..ee6d7e8f16f 100644 --- a/src/libextra/btree.rs +++ b/src/libextra/btree.rs @@ -15,7 +15,7 @@ //! Structure inspired by github user davidhalperin's gist. #[allow(dead_code)]; -use std::util::replace; +#[allow(unused_variable)]; ///A B-tree contains a root node (which contains a vector of elements), ///a length (the height of the tree), and lower and upper bounds on the @@ -33,7 +33,7 @@ pub struct BTree { //especially during insertions and deletions. //Using the swap or replace methods is one option for replacing dependence on Clone, or //changing the way in which the BTree is stored could also potentially work. -impl BTree { +impl BTree { ///Returns new BTree with root node (leaf) and user-supplied lower bound pub fn new(k: K, v: V, lb: uint) -> BTree { @@ -58,27 +58,43 @@ impl BTree { } } - ///Implements the Clone trait for the BTree. - ///Uses a helper function/constructor to produce a new BTree. - pub fn clone(&self) -> BTree { - return BTree::new_with_node_len(self.root.clone(), self.len, self.lower_bound); + + ///Stub for add method in progress. + pub fn add(self, k: K, v: V) -> BTree { + //replace(&self.root,self.root.add(k, v)); + return BTree::new(k, v, 2); } +} + +impl BTree { ///Returns the value of a given key, which may not exist in the tree. ///Calls the root node's get method. pub fn get(self, k: K) -> Option { return self.root.get(k); } +} - ///Checks to see if the key already exists in the tree, and if it is not, - ///the key-value pair is added to the tree by calling add on the root node. - pub fn add(self, k: K, v: V) -> bool { - let is_get = &self.clone().get(k.clone()); - if is_get.is_some(){ return false; } - else { - replace(&mut self.root.clone(),self.root.add(k.clone(), v)); - return true; - } +impl Clone for BTree { + ///Implements the Clone trait for the BTree. + ///Uses a helper function/constructor to produce a new BTree. + fn clone(&self) -> BTree { + BTree::new_with_node_len(self.root.clone(), self.len, self.lower_bound) + } +} + + +impl TotalEq for BTree { + ///Testing equality on BTrees by comparing the root. + fn equals(&self, other: &BTree) -> bool { + self.root.cmp(&other.root) == Equal + } +} + +impl TotalOrd for BTree { + ///Returns an ordering based on the root nodes of each BTree. + fn cmp(&self, other: &BTree) -> Ordering { + self.root.cmp(&other.root) } } @@ -103,10 +119,10 @@ enum Node { //Node functions/methods -impl Node { +impl Node { ///Differentiates between leaf and branch nodes. - fn is_leaf(&self) -> bool{ + fn is_leaf(&self) -> bool { match self{ &LeafNode(..) => true, &BranchNode(..) => false @@ -118,12 +134,20 @@ impl Node { LeafNode(Leaf::new(vec)) } + ///Creates a new branch node given a vector of an elements and a pointer to a rightmost child. fn new_branch(vec: ~[BranchElt], right: ~Node) -> Node { BranchNode(Branch::new(vec, right)) } + ///A placeholder/stub for add + ///Currently returns a leaf node with a single value (the added one) + fn add(self, k: K, v: V) -> Node { + return Node::new_leaf(~[LeafElt::new(k, v)]); + } +} +impl Node { ///Returns the corresponding value to the provided key. ///get() is called in different ways on a branch or a leaf. fn get(&self, k: K) -> Option { @@ -132,84 +156,71 @@ impl Node { BranchNode(ref branch) => return branch.get(k) } } - - ///A placeholder for add - ///Currently returns a leaf node with a single value (the added one) - fn add(self, k: K, v: V) -> Node { - return Node::new_leaf(~[LeafElt::new(k, v)]); - } } -//Again, this might not be necessary in the future. impl Clone for Node { - ///Returns a new node based on whether or not it is a branch or a leaf. fn clone(&self) -> Node { match *self { LeafNode(ref leaf) => { - return Node::new_leaf(leaf.elts.clone()); + Node::new_leaf(leaf.elts.clone()) } BranchNode(ref branch) => { - return Node::new_branch(branch.elts.clone(), - branch.rightmost_child.clone()); + Node::new_branch(branch.elts.clone(), + branch.rightmost_child.clone()) } } } } -//The following impl is unfinished. Old iterations of code are left in for -//future reference when implementing this trait (commented-out). -impl TotalOrd for Node { +impl TotalEq for Node { + ///Returns whether two nodes are equal + fn equals(&self, other: &Node) -> bool{ + match *self{ + BranchNode(ref branch) => { + match *other{ + BranchNode(ref branch2) => branch.cmp(branch2) == Equal, + LeafNode(ref leaf) => false + } + } - ///Placeholder for an implementation of TotalOrd for Nodes. - #[allow(unused_variable)] + LeafNode(ref leaf) => { + match *other{ + LeafNode(ref leaf2) => leaf.cmp(leaf2) == Equal, + BranchNode(ref branch) => false + } + } + } + } +} + +impl TotalOrd for Node { + ///Implementation of TotalOrd for Nodes. fn cmp(&self, other: &Node) -> Ordering { - //Requires a match statement--defer these procs to branch and leaf. - /* if self.elts[0].less_than(other.elts[0]) { return Less} - if self.elts[0].greater_than(other.elts[0]) {return Greater} - else {return Equal} - */ - return Equal; + match *self { + LeafNode(ref leaf) => { + match *other { + LeafNode(ref leaf2) => leaf.cmp(leaf2), + BranchNode(_) => Less + } + } + BranchNode(ref branch) => { + match *other { + BranchNode(ref branch2) => branch.cmp(branch2), + LeafNode(_) => Greater + } + } + } } } -//The following impl is unfinished. Old iterations of code are left in for -//future reference when implementing this trait (commented-out). -impl TotalEq for Node { - - ///Placeholder for an implementation of TotalEq for Nodes. - #[allow(unused_variable)] - fn equals(&self, other: &Node) -> bool { - /* put in a match and defer this stuff to branch and leaf - - let mut shorter = 0; - if self.elts.len() <= other.elts.len(){ - shorter = self.elts.len(); - } - else{ - shorter = other.elts.len(); - } - let mut i = 0; - while i < shorter{ - if !self.elts[i].has_key(other.elts[i].key){ - return false; - } - i +=1; - } - return true; - */ - return true; - } -} - - impl ToStr for Node { ///Returns a string representation of a Node. ///The Branch's to_str() is not implemented yet. fn to_str(&self) -> ~str { match *self { LeafNode(ref leaf) => leaf.to_str(), - BranchNode(..) => ~"" + BranchNode(ref branch) => branch.to_str() } } } @@ -228,8 +239,7 @@ struct Branch { } -impl Leaf { - +impl Leaf { ///Creates a new Leaf from a vector of LeafElts. fn new(vec: ~[LeafElt]) -> Leaf { Leaf { @@ -237,6 +247,15 @@ impl Leaf { } } + ///Placeholder for add method in progress. + ///Currently returns a new Leaf containing a single LeafElt. + fn add(&self, k: K, v: V) -> Node { + return Node::new_leaf(~[LeafElt::new(k, v)]); + } + +} + +impl Leaf { ///Returns the corresponding value to the supplied key. fn get(&self, k: K) -> Option { for s in self.elts.iter() { @@ -248,31 +267,45 @@ impl Leaf { } return None; } - - ///Placeholder for add method in progress. - ///Currently returns a new Leaf containing a single LeafElt. - fn add(&self, k: K, v: V) -> Node { - return Node::new_leaf(~[LeafElt::new(k, v)]); - } - } +impl Clone for Leaf { + ///Returns a new Leaf with the same elts. + fn clone(&self) -> Leaf { + Leaf::new(self.elts.clone()) + } +} + +impl TotalEq for Leaf { + ///Implementation of equals function for leaves that compares LeafElts. + fn equals(&self, other: &Leaf) -> bool { + self.elts.equals(&other.elts) + } +} + +impl TotalOrd for Leaf { + ///Returns an ordering based on the first element of each Leaf. + fn cmp(&self, other: &Leaf) -> Ordering { + if self.elts.len() > other.elts.len() { + return Greater; + } + if self.elts.len() < other.elts.len() { + return Less; + } + self.elts[0].cmp(&other.elts[0]) + } +} + + impl ToStr for Leaf { - ///Returns a string representation of a Leaf. fn to_str(&self) -> ~str { - let mut ret = ~""; - for s in self.elts.iter() { - ret = ret + " // " + s.to_str(); - } - ret + self.elts.iter().map(|s| s.to_str()).to_owned_vec().connect(" // ") } - } -impl Branch { - +impl Branch { ///Creates a new Branch from a vector of BranchElts and a rightmost child (a node). fn new(vec: ~[BranchElt], right: ~Node) -> Branch { Branch { @@ -281,6 +314,13 @@ impl Branch { } } + ///Placeholder for add method in progress + fn add(&self, k: K, v: V) -> Node { + return Node::new_leaf(~[LeafElt::new(k, v)]); + } +} + +impl Branch { ///Returns the corresponding value to the supplied key. ///If the key is not there, find the child that might hold it. fn get(&self, k: K) -> Option { @@ -292,13 +332,44 @@ impl Branch { _ => {} } } - return self.rightmost_child.get(k); + self.rightmost_child.get(k) } +} +impl Clone for Branch { + ///Returns a new branch using the clone methods of the Branch's internal variables. + fn clone(&self) -> Branch { + Branch::new(self.elts.clone(), self.rightmost_child.clone()) + } +} - ///Placeholder for add method in progress - fn add(&self, k: K, v: V) -> Node { - return Node::new_leaf(~[LeafElt::new(k, v)]); +impl TotalEq for Branch { + ///Equals function for Branches--compares all the elements in each branch + fn equals(&self, other: &Branch) -> bool { + self.elts.equals(&other.elts) + } +} + +impl TotalOrd for Branch { + ///Compares the first elements of two branches to determine an ordering + fn cmp(&self, other: &Branch) -> Ordering { + if self.elts.len() > other.elts.len() { + return Greater; + } + if self.elts.len() < other.elts.len() { + return Less; + } + self.elts[0].cmp(&other.elts[0]) + } +} + +impl ToStr for Branch { + ///Returns a string representation of a Branch. + fn to_str(&self) -> ~str { + let mut ret = self.elts.iter().map(|s| s.to_str()).to_owned_vec().connect(" // "); + ret.push_str(" // "); + ret.push_str(self.rightmost_child.to_str()); + ret } } @@ -315,8 +386,7 @@ struct BranchElt { value: V } -impl LeafElt { - +impl LeafElt { ///Creates a new LeafElt from a supplied key-value pair. fn new(k: K, v: V) -> LeafElt { LeafElt { @@ -356,28 +426,36 @@ impl LeafElt { } } -//This may be eliminated in the future to perserve efficiency by adjusting the way -//the BTree as a whole is stored in memory. impl Clone for LeafElt { - ///Returns a new LeafElt by cloning the key and value. fn clone(&self) -> LeafElt { - return LeafElt::new(self.key.clone(), self.value.clone()); + LeafElt::new(self.key.clone(), self.value.clone()) + } +} + +impl TotalEq for LeafElt { + ///TotalEq for LeafElts + fn equals(&self, other: &LeafElt) -> bool { + self.key.equals(&other.key) && self.value.equals(&other.value) + } +} + +impl TotalOrd for LeafElt { + ///Returns an ordering based on the keys of the LeafElts. + fn cmp(&self, other: &LeafElt) -> Ordering { + self.key.cmp(&other.key) } } impl ToStr for LeafElt { - ///Returns a string representation of a LeafElt. fn to_str(&self) -> ~str { - return "Key: " + self.key.to_str() + ", value: " - + self.value.to_str() + "; "; + format!("Key: {}, value: {};", + self.key.to_str(), self.value.to_str()) } - } -impl BranchElt { - +impl BranchElt { ///Creates a new BranchElt from a supplied key, value, and left child. fn new(k: K, v: V, n: Node) -> BranchElt { BranchElt { @@ -394,59 +472,122 @@ impl BranchElt { } } -impl Clone for BranchElt { +impl Clone for BranchElt { ///Returns a new BranchElt by cloning the key, value, and left child. fn clone(&self) -> BranchElt { - return BranchElt::new(self.key.clone(), - self.value.clone(), - self.left.clone()); + BranchElt::new(self.key.clone(), + self.value.clone(), + self.left.clone()) + } +} + +impl TotalEq for BranchElt{ + ///TotalEq for BranchElts + fn equals(&self, other: &BranchElt) -> bool { + self.key.equals(&other.key)&&self.value.equals(&other.value) + } +} + +impl TotalOrd for BranchElt { + ///Fulfills TotalOrd for BranchElts + fn cmp(&self, other: &BranchElt) -> Ordering { + self.key.cmp(&other.key) + } +} + +impl ToStr for BranchElt { + ///Returns string containing key, value, and child (which should recur to a leaf) + ///Consider changing in future to be more readable. + fn to_str(&self) -> ~str { + format!("Key: {}, value: {}, child: {};", + self.key.to_str(), self.value.to_str(), self.left.to_str()) } } #[cfg(test)] -mod test_btree{ +mod test_btree { use super::{BTree, LeafElt}; - ///Tests the functionality of the add methods (which are unfinished). - #[test] + //Tests the functionality of the add methods (which are unfinished). + /*#[test] fn add_test(){ let b = BTree::new(1, ~"abc", 2); let is_add = b.add(2, ~"xyz"); assert!(is_add); - } + }*/ - ///Tests the functionality of the get method. + //Tests the functionality of the get method. #[test] - fn get_test(){ + fn get_test() { let b = BTree::new(1, ~"abc", 2); let val = b.get(1); assert_eq!(val, Some(~"abc")); } - ///Tests the LeafElt's less_than() method. + //Tests the LeafElt's less_than() method. #[test] - fn leaf_lt(){ + fn leaf_lt() { let l1 = LeafElt::new(1, ~"abc"); let l2 = LeafElt::new(2, ~"xyz"); assert!(l1.less_than(l2)); } - ///Tests the LeafElt's greater_than() method. + //Tests the LeafElt's greater_than() method. #[test] - fn leaf_gt(){ + fn leaf_gt() { let l1 = LeafElt::new(1, ~"abc"); let l2 = LeafElt::new(2, ~"xyz"); assert!(l2.greater_than(l1)); } - ///Tests the LeafElt's has_key() method. + //Tests the LeafElt's has_key() method. #[test] - fn leaf_hk(){ + fn leaf_hk() { let l1 = LeafElt::new(1, ~"abc"); assert!(l1.has_key(1)); } + + //Tests the BTree's clone() method. + #[test] + fn btree_clone_test() { + let b = BTree::new(1, ~"abc", 2); + let b2 = b.clone(); + assert!(b.root.equals(&b2.root)) + } + + //Tests the BTree's cmp() method when one node is "less than" another. + #[test] + fn btree_cmp_test_less() { + let b = BTree::new(1, ~"abc", 2); + let b2 = BTree::new(2, ~"bcd", 2); + assert!(&b.cmp(&b2) == &Less) + } + + //Tests the BTree's cmp() method when two nodes are equal. + #[test] + fn btree_cmp_test_eq() { + let b = BTree::new(1, ~"abc", 2); + let b2 = BTree::new(1, ~"bcd", 2); + assert!(&b.cmp(&b2) == &Equal) + } + + //Tests the BTree's cmp() method when one node is "greater than" another. + #[test] + fn btree_cmp_test_greater() { + let b = BTree::new(1, ~"abc", 2); + let b2 = BTree::new(2, ~"bcd", 2); + assert!(&b2.cmp(&b) == &Greater) + } + + //Tests the BTree's to_str() method. + #[test] + fn btree_tostr_test() { + let b = BTree::new(1, ~"abc", 2); + assert_eq!(b.to_str(), ~"Key: 1, value: abc;") + } + }