diff --git a/src/libextra/btree.rs b/src/libextra/btree.rs new file mode 100644 index 00000000000..d650769d70f --- /dev/null +++ b/src/libextra/btree.rs @@ -0,0 +1,449 @@ +// 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. + + +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 + 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 + } + } + + ///Implements the Clone trait for the BTree. + ///Uses a helper function/constructor to produce a new BTree. + 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. + 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. + 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::*; + + ///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)); + } +} + diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs index 2ac12373794..8bb99617274 100644 --- a/src/libextra/lib.rs +++ b/src/libextra/lib.rs @@ -67,6 +67,7 @@ pub mod sort; pub mod dlist; pub mod treemap; +pub mod btree; // And ... other stuff