// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // // btree.rs // //! Starting implementation of a btree for rust. //! Structure inspired by github user davidhalperin's gist. #[allow(dead_code)]; #[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 ///number of elements that a given node can contain. #[allow(missing_doc)] pub struct BTree { priv root: Node, priv len: uint, priv lower_bound: uint, priv upper_bound: uint } //We would probably want to remove the dependence on the Clone trait in the future. //It is here as a crutch to ensure values can be passed around through the tree's nodes //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 { ///Returns new BTree with root node (leaf) and user-supplied lower bound pub fn new(k: K, v: V, lb: uint) -> BTree { BTree { root: Node::new_leaf(~[LeafElt::new(k, v)]), len: 1, lower_bound: lb, upper_bound: 2 * lb } } ///Helper function for clone: returns new BTree with supplied root node, ///length, and lower bound. For use when the length is known already. fn new_with_node_len(n: Node, length: uint, lb: uint) -> BTree { BTree { root: n, len: length, lower_bound: lb, upper_bound: 2 * lb } } ///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); } } 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) } } impl ToStr for BTree { ///Returns a string representation of the BTree fn to_str(&self) -> ~str { let ret = self.root.to_str(); ret } } //Node types //A node is either a LeafNode or a BranchNode, which contain either a Leaf or a Branch. //Branches contain BranchElts, which contain a left child (another node) and a key-value //pair. Branches also contain the rightmost child of the elements in the array. //Leaves contain LeafElts, which do not have children. enum Node { LeafNode(Leaf), BranchNode(Branch) } //Node functions/methods impl Node { ///Differentiates between leaf and branch nodes. fn is_leaf(&self) -> bool { match self{ &LeafNode(..) => true, &BranchNode(..) => false } } ///Creates a new leaf node given a vector of elements. fn new_leaf(vec: ~[LeafElt]) -> 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 { match *self { LeafNode(ref leaf) => return leaf.get(k), BranchNode(ref branch) => return branch.get(k) } } } 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) => { Node::new_leaf(leaf.elts.clone()) } BranchNode(ref branch) => { Node::new_branch(branch.elts.clone(), branch.rightmost_child.clone()) } } } } 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 } } 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 { 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 } } } } } 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(ref branch) => branch.to_str() } } } //A leaf is a vector with elements that contain no children. A leaf also //does not contain a rightmost child. struct Leaf { elts: ~[LeafElt] } //Vector of values with children, plus a rightmost child (greater than all) struct Branch { elts: ~[BranchElt], rightmost_child: ~Node } impl Leaf { ///Creates a new Leaf from a vector of LeafElts. fn new(vec: ~[LeafElt]) -> Leaf { Leaf { elts: vec } } ///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() { let order = s.key.cmp(&k); match order { Equal => return Some(s.value.clone()), _ => {} } } return None; } } 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 { self.elts.iter().map(|s| s.to_str()).to_owned_vec().connect(" // ") } } 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 { elts: vec, rightmost_child: right } } ///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 { for s in self.elts.iter() { let order = s.key.cmp(&k); match order { Less => return s.left.get(k), Equal => return Some(s.value.clone()), _ => {} } } 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()) } } 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 } } //A LeafElt containts no left child, but a key-value pair. struct LeafElt { key: K, value: V } //A BranchElt has a left child in addition to a key-value pair. struct BranchElt { left: Node, key: K, value: V } impl LeafElt { ///Creates a new LeafElt from a supplied key-value pair. fn new(k: K, v: V) -> LeafElt { LeafElt { key: k, value: v } } ///Compares another LeafElt against itself and determines whether ///the original LeafElt's key is less than the other one's key. fn less_than(&self, other: LeafElt) -> bool { let order = self.key.cmp(&other.key); match order { Less => true, _ => false } } ///Compares another LeafElt against itself and determines whether ///the original LeafElt's key is greater than the other one's key. fn greater_than(&self, other: LeafElt) -> bool { let order = self.key.cmp(&other.key); match order { Greater => true, _ => false } } ///Takes a key and determines whether its own key and the supplied key ///are the same. fn has_key(&self, other: K) -> bool { let order = self.key.cmp(&other); match order { Equal => true, _ => false } } } impl Clone for LeafElt { ///Returns a new LeafElt by cloning the key and value. fn clone(&self) -> LeafElt { 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 { format!("Key: {}, value: {};", self.key.to_str(), self.value.to_str()) } } impl BranchElt { ///Creates a new BranchElt from a supplied key, value, and left child. fn new(k: K, v: V, n: Node) -> BranchElt { BranchElt { left: n, key: k, value: v } } ///Placeholder for add method in progress. ///Overall implementation will determine the actual return value of this method. fn add(&self, k: K, v: V) -> LeafElt { return LeafElt::new(k, v); } } impl Clone for BranchElt { ///Returns a new BranchElt by cloning the key, value, and left child. fn clone(&self) -> BranchElt { 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 { use super::{BTree, LeafElt}; //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. #[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. #[test] 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. #[test] 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. #[test] 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;") } }