// 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)]; use std::util::replace; ///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 { root: Node, len: uint, lower_bound: uint, 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. pub fn new_with_node_len(n: Node, length: uint, lb: uint) -> BTree { BTree { root: n, len: length, lower_bound: lb, upper_bound: 2 * lb } } ///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); } ///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 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)) } ///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) } } ///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()); } BranchNode(ref branch) => { return 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 { ///Placeholder for an implementation of TotalOrd for Nodes. #[allow(unused_variable)] 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; } } //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(..) => ~"" } } } //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 } } ///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; } ///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 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 } } 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 } } ///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()), _ => {} } } return self.rightmost_child.get(k); } ///Placeholder for add method in progress fn add(&self, k: K, v: V) -> Node { return Node::new_leaf(~[LeafElt::new(k, v)]); } } //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 } } } //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()); } } 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() + "; "; } } 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 { return BranchElt::new(self.key.clone(), self.value.clone(), self.left.clone()); } } #[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)); } }