complete btree rewrite
Replaces BTree with BTreeMap and BTreeSet, which are completely new implementations. BTreeMap's internal Node representation is particularly inefficient at the moment to make this first implementation easy to reason about and fairly safe. Both collections are also currently missing some of the tooling specific to sorted collections, which is planned as future work pending reform of these APIs. General implementation issues are discussed with TODOs internally Perf results on x86_64 Linux: test treemap::bench::find_rand_100 ... bench: 76 ns/iter (+/- 4) test treemap::bench::find_rand_10_000 ... bench: 163 ns/iter (+/- 6) test treemap::bench::find_seq_100 ... bench: 77 ns/iter (+/- 3) test treemap::bench::find_seq_10_000 ... bench: 115 ns/iter (+/- 1) test treemap::bench::insert_rand_100 ... bench: 111 ns/iter (+/- 1) test treemap::bench::insert_rand_10_000 ... bench: 996 ns/iter (+/- 18) test treemap::bench::insert_seq_100 ... bench: 486 ns/iter (+/- 20) test treemap::bench::insert_seq_10_000 ... bench: 800 ns/iter (+/- 15) test btree::map::bench::find_rand_100 ... bench: 74 ns/iter (+/- 4) test btree::map::bench::find_rand_10_000 ... bench: 153 ns/iter (+/- 5) test btree::map::bench::find_seq_100 ... bench: 82 ns/iter (+/- 1) test btree::map::bench::find_seq_10_000 ... bench: 108 ns/iter (+/- 0) test btree::map::bench::insert_rand_100 ... bench: 220 ns/iter (+/- 1) test btree::map::bench::insert_rand_10_000 ... bench: 620 ns/iter (+/- 16) test btree::map::bench::insert_seq_100 ... bench: 411 ns/iter (+/- 12) test btree::map::bench::insert_seq_10_000 ... bench: 534 ns/iter (+/- 14) BTreeMap still has a lot of room for optimization, but it's already beating out TreeMap on most access patterns. [breaking-change]
This commit is contained in:
parent
d299bafb31
commit
b6edc59413
@ -1,919 +0,0 @@
|
||||
// Copyright 2012-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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
|
||||
// NB. this is not deprecated for removal, just deprecating the
|
||||
// current implementation. If the major pain-points are addressed
|
||||
// (overuse of by-value self and .clone), this can be removed.
|
||||
#![deprecated = "the current implementation is extremely inefficient, \
|
||||
prefer a HashMap, TreeMap or TrieMap"]
|
||||
#![allow(deprecated)]
|
||||
|
||||
//! Starting implementation of a B-tree for Rust.
|
||||
//! Structure inspired by Github user davidhalperin's gist.
|
||||
|
||||
// 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.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::fmt;
|
||||
use core::fmt::Show;
|
||||
|
||||
use MutableSeq;
|
||||
use vec::Vec;
|
||||
|
||||
#[allow(missing_doc)]
|
||||
pub struct BTree<K, V> {
|
||||
root: Node<K, V>,
|
||||
len: uint,
|
||||
lower_bound: uint,
|
||||
upper_bound: uint
|
||||
}
|
||||
|
||||
impl<K: Ord, V> BTree<K, V> {
|
||||
/// Returns new `BTree` with root node (leaf) and user-supplied lower bound
|
||||
/// The lower bound applies to every node except the root node.
|
||||
pub fn new(k: K, v: V, lb: uint) -> BTree<K, V> {
|
||||
BTree {
|
||||
root: Node::new_leaf(vec!(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<K, V>,
|
||||
length: uint,
|
||||
lb: uint) -> BTree<K, V> {
|
||||
BTree {
|
||||
root: n,
|
||||
len: length,
|
||||
lower_bound: lb,
|
||||
upper_bound: 2 * lb
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
impl<K: Clone + Ord, V: Clone> BTree<K, V> {
|
||||
/// 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<V> {
|
||||
return self.root.get(k);
|
||||
}
|
||||
|
||||
/// An insert method that uses the `clone` method for support.
|
||||
pub fn insert(mut self, k: K, v: V) -> BTree<K, V> {
|
||||
let (a, b) = self.root.clone().insert(k, v, self.upper_bound.clone());
|
||||
if b {
|
||||
match a.clone() {
|
||||
LeafNode(leaf) => {
|
||||
self.root = Node::new_leaf(leaf.clone().elts);
|
||||
}
|
||||
BranchNode(branch) => {
|
||||
self.root = Node::new_branch(branch.clone().elts,
|
||||
branch.clone().rightmost_child);
|
||||
}
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for BTree<K, V> {
|
||||
fn clone(&self) -> BTree<K, V> {
|
||||
BTree::new_with_node_len(self.root.clone(), self.len, self.lower_bound)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialEq for BTree<K, V> {
|
||||
fn eq(&self, other: &BTree<K, V>) -> bool {
|
||||
self.root.cmp(&other.root) == Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for BTree<K, V> {}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for BTree<K, V> {
|
||||
fn partial_cmp(&self, other: &BTree<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for BTree<K, V> {
|
||||
/// Returns an ordering based on the root nodes of each `BTree`.
|
||||
fn cmp(&self, other: &BTree<K, V>) -> Ordering {
|
||||
self.root.cmp(&other.root)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for BTree<K, V> {
|
||||
/// Returns a string representation of the `BTree`.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.root.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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<K, V> {
|
||||
LeafNode(Leaf<K, V>),
|
||||
BranchNode(Branch<K, V>)
|
||||
}
|
||||
|
||||
|
||||
impl<K: Ord, V> Node<K, V> {
|
||||
/// Creates a new leaf node given a vector of elements.
|
||||
fn new_leaf(vec: Vec<LeafElt<K, V>>) -> Node<K,V> {
|
||||
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: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
|
||||
-> Node<K, V> {
|
||||
BranchNode(Branch::new(vec, right))
|
||||
}
|
||||
|
||||
/// Determines whether the given Node contains a Branch or a Leaf.
|
||||
/// Used in testing.
|
||||
fn is_leaf(&self) -> bool {
|
||||
match self {
|
||||
&LeafNode(..) => true,
|
||||
&BranchNode(..) => false
|
||||
}
|
||||
}
|
||||
|
||||
/// A binary search function for Nodes.
|
||||
/// Calls either the Branch's or the Leaf's bsearch function.
|
||||
fn bsearch_node(&self, k: K) -> Option<uint> {
|
||||
match self {
|
||||
&LeafNode(ref leaf) => leaf.bsearch_leaf(k),
|
||||
&BranchNode(ref branch) => branch.bsearch_branch(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Node<K, V> {
|
||||
/// 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<V> {
|
||||
match *self {
|
||||
LeafNode(ref leaf) => return leaf.get(k),
|
||||
BranchNode(ref branch) => return branch.get(k)
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches on the `Node`, then performs and returns the appropriate insert method.
|
||||
fn insert(self, k: K, v: V, ub: uint) -> (Node<K, V>, bool) {
|
||||
match self {
|
||||
LeafNode(leaf) => leaf.insert(k, v, ub),
|
||||
BranchNode(branch) => branch.insert(k, v, ub)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for Node<K, V> {
|
||||
/// Returns a new `Node` based on whether or not it is a branch or a leaf.
|
||||
fn clone(&self) -> Node<K, V> {
|
||||
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<K: Ord, V: Eq> PartialEq for Node<K, V> {
|
||||
fn eq(&self, other: &Node<K, V>) -> bool {
|
||||
match *self{
|
||||
BranchNode(ref branch) => {
|
||||
if other.is_leaf() {
|
||||
return false;
|
||||
}
|
||||
match *other {
|
||||
BranchNode(ref branch2) => branch.cmp(branch2) == Equal,
|
||||
LeafNode(..) => false
|
||||
}
|
||||
}
|
||||
LeafNode(ref leaf) => {
|
||||
match *other {
|
||||
LeafNode(ref leaf2) => leaf.cmp(leaf2) == Equal,
|
||||
BranchNode(..) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for Node<K, V> {}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for Node<K, V> {
|
||||
fn partial_cmp(&self, other: &Node<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for Node<K, V> {
|
||||
/// Implementation of `Ord` for `Node`s.
|
||||
fn cmp(&self, other: &Node<K, V>) -> 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<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for Node<K, V> {
|
||||
/// Returns a string representation of a `Node`.
|
||||
/// Will iterate over the Node and show `Key: x, value: y, child: ()`
|
||||
/// for all elements in the `Node`. `child` only exists if the `Node` contains
|
||||
/// a branch.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
LeafNode(ref leaf) => leaf.fmt(f),
|
||||
BranchNode(ref branch) => branch.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A leaf is a vector with elements that contain no children. A leaf also
|
||||
// does not contain a rightmost child.
|
||||
struct Leaf<K, V> {
|
||||
elts: Vec<LeafElt<K, V>>
|
||||
}
|
||||
|
||||
// Vector of values with children, plus a rightmost child (greater than all)
|
||||
struct Branch<K, V> {
|
||||
elts: Vec<BranchElt<K,V>>,
|
||||
rightmost_child: Box<Node<K, V>>,
|
||||
}
|
||||
|
||||
|
||||
impl<K: Ord, V> Leaf<K, V> {
|
||||
/// Creates a new `Leaf` from a vector of `LeafElts`.
|
||||
fn new(vec: Vec<LeafElt<K, V>>) -> Leaf<K, V> {
|
||||
Leaf {
|
||||
elts: vec
|
||||
}
|
||||
}
|
||||
|
||||
/// Searches a leaf for a spot for a new element using a binary search.
|
||||
/// Returns `None` if the element is already in the vector.
|
||||
fn bsearch_leaf(&self, k: K) -> Option<uint> {
|
||||
let mut high: uint = self.elts.len();
|
||||
let mut low: uint = 0;
|
||||
let mut midpoint: uint = (high - low) / 2 ;
|
||||
if midpoint == high {
|
||||
midpoint = 0;
|
||||
}
|
||||
loop {
|
||||
let order = self.elts[midpoint].key.cmp(&k);
|
||||
match order {
|
||||
Equal => {
|
||||
return None;
|
||||
}
|
||||
Greater => {
|
||||
if midpoint > 0 {
|
||||
if self.elts[midpoint - 1].key.cmp(&k) == Less {
|
||||
return Some(midpoint);
|
||||
}
|
||||
else {
|
||||
let tmp = midpoint;
|
||||
midpoint = midpoint / 2;
|
||||
high = tmp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Some(0);
|
||||
}
|
||||
}
|
||||
Less => {
|
||||
if midpoint + 1 < self.elts.len() {
|
||||
if self.elts[midpoint + 1].key.cmp(&k) == Greater {
|
||||
return Some(midpoint);
|
||||
}
|
||||
else {
|
||||
let tmp = midpoint;
|
||||
midpoint = (high + low) / 2;
|
||||
low = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Some(self.elts.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Leaf<K, V> {
|
||||
/// Returns the corresponding value to the supplied key.
|
||||
fn get(&self, k: K) -> Option<V> {
|
||||
for s in self.elts.iter() {
|
||||
let order = s.key.cmp(&k);
|
||||
match order {
|
||||
Equal => return Some(s.value.clone()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Uses `clone()` to facilitate inserting new elements into a tree.
|
||||
fn insert(mut self, k: K, v: V, ub: uint) -> (Node<K, V>, bool) {
|
||||
let to_insert = LeafElt::new(k, v);
|
||||
let index: Option<uint> = self.bsearch_leaf(to_insert.clone().key);
|
||||
//Check index to see whether we actually inserted the element into the vector.
|
||||
match index {
|
||||
//If the index is None, the new element already exists in the vector.
|
||||
None => {
|
||||
return (Node::new_leaf(self.clone().elts), false);
|
||||
}
|
||||
//If there is an index, insert at that index.
|
||||
Some(i) => {
|
||||
if i >= self.elts.len() {
|
||||
self.elts.push(to_insert.clone());
|
||||
}
|
||||
else {
|
||||
self.elts.insert(i, to_insert.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
//If we have overfilled the vector (by making its size greater than the
|
||||
//upper bound), we return a new Branch with one element and two children.
|
||||
if self.elts.len() > ub {
|
||||
let midpoint_opt = self.elts.remove(ub / 2);
|
||||
let midpoint = midpoint_opt.unwrap();
|
||||
let (left_leaf, right_leaf) = self.elts.partition(|le|
|
||||
le.key.cmp(&midpoint.key.clone())
|
||||
== Less);
|
||||
let branch_return = Node::new_branch(vec!(BranchElt::new(midpoint.key.clone(),
|
||||
midpoint.value.clone(),
|
||||
box Node::new_leaf(left_leaf))),
|
||||
box Node::new_leaf(right_leaf));
|
||||
return (branch_return, true);
|
||||
}
|
||||
(Node::new_leaf(self.elts.clone()), true)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for Leaf<K, V> {
|
||||
/// Returns a new `Leaf` with the same elts.
|
||||
fn clone(&self) -> Leaf<K, V> {
|
||||
Leaf::new(self.elts.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialEq for Leaf<K, V> {
|
||||
fn eq(&self, other: &Leaf<K, V>) -> bool {
|
||||
self.elts == other.elts
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for Leaf<K, V> {}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for Leaf<K, V> {
|
||||
fn partial_cmp(&self, other: &Leaf<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for Leaf<K, V> {
|
||||
/// Returns an ordering based on the first element of each `Leaf`.
|
||||
fn cmp(&self, other: &Leaf<K, V>) -> 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<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for Leaf<K, V> {
|
||||
/// Returns a string representation of a `Leaf`.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for (i, s) in self.elts.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, " // ")) }
|
||||
try!(write!(f, "{}", *s))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<K: Ord, V> Branch<K, V> {
|
||||
/// Creates a new `Branch` from a vector of `BranchElts` and a rightmost child (a node).
|
||||
fn new(vec: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
|
||||
-> Branch<K, V> {
|
||||
Branch {
|
||||
elts: vec,
|
||||
rightmost_child: right
|
||||
}
|
||||
}
|
||||
|
||||
fn bsearch_branch(&self, k: K) -> Option<uint> {
|
||||
let mut midpoint: uint = self.elts.len() / 2;
|
||||
let mut high: uint = self.elts.len();
|
||||
let mut low: uint = 0u;
|
||||
if midpoint == high {
|
||||
midpoint = 0u;
|
||||
}
|
||||
loop {
|
||||
let order = self.elts[midpoint].key.cmp(&k);
|
||||
match order {
|
||||
Equal => {
|
||||
return None;
|
||||
}
|
||||
Greater => {
|
||||
if midpoint > 0 {
|
||||
if self.elts[midpoint - 1].key.cmp(&k) == Less {
|
||||
return Some(midpoint);
|
||||
}
|
||||
else {
|
||||
let tmp = midpoint;
|
||||
midpoint = (midpoint - low) / 2;
|
||||
high = tmp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Some(0);
|
||||
}
|
||||
}
|
||||
Less => {
|
||||
if midpoint + 1 < self.elts.len() {
|
||||
if self.elts[midpoint + 1].key.cmp(&k) == Greater {
|
||||
return Some(midpoint);
|
||||
}
|
||||
else {
|
||||
let tmp = midpoint;
|
||||
midpoint = (high - midpoint) / 2;
|
||||
low = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Some(self.elts.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Branch<K, V> {
|
||||
/// 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<V> {
|
||||
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)
|
||||
}
|
||||
|
||||
/// An insert method that uses `.clone()` for support.
|
||||
fn insert(mut self, k: K, v: V, ub: uint) -> (Node<K, V>, bool) {
|
||||
let mut new_branch = Node::new_branch(self.clone().elts, self.clone().rightmost_child);
|
||||
let mut outcome = false;
|
||||
let index: Option<uint> = new_branch.bsearch_node(k.clone());
|
||||
//First, find which path down the tree will lead to the appropriate leaf
|
||||
//for the key-value pair.
|
||||
match index.clone() {
|
||||
None => {
|
||||
return (Node::new_branch(self.clone().elts,
|
||||
self.clone().rightmost_child),
|
||||
outcome);
|
||||
}
|
||||
Some(i) => {
|
||||
if i == self.elts.len() {
|
||||
let new_outcome = self.clone().rightmost_child.insert(k.clone(),
|
||||
v.clone(),
|
||||
ub.clone());
|
||||
new_branch = new_outcome.clone().val0();
|
||||
outcome = new_outcome.val1();
|
||||
}
|
||||
else {
|
||||
let new_outcome = self.elts[i].left.clone().insert(k.clone(),
|
||||
v.clone(),
|
||||
ub.clone());
|
||||
new_branch = new_outcome.clone().val0();
|
||||
outcome = new_outcome.val1();
|
||||
}
|
||||
//Check to see whether a branch or a leaf was returned from the
|
||||
//tree traversal.
|
||||
match new_branch.clone() {
|
||||
//If we have a leaf, we do not need to resize the tree,
|
||||
//so we can return false.
|
||||
LeafNode(..) => {
|
||||
if i == self.elts.len() {
|
||||
self.rightmost_child = box new_branch.clone();
|
||||
}
|
||||
else {
|
||||
self.elts.get_mut(i).left = box new_branch.clone();
|
||||
}
|
||||
return (Node::new_branch(self.clone().elts,
|
||||
self.clone().rightmost_child),
|
||||
true);
|
||||
}
|
||||
//If we have a branch, we might need to refactor the tree.
|
||||
BranchNode(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
//If we inserted something into the tree, do the following:
|
||||
if outcome {
|
||||
match new_branch.clone() {
|
||||
//If we have a new leaf node, integrate it into the current branch
|
||||
//and return it, saying we have inserted a new element.
|
||||
LeafNode(..) => {
|
||||
if index.unwrap() == self.elts.len() {
|
||||
self.rightmost_child = box new_branch;
|
||||
}
|
||||
else {
|
||||
self.elts.get_mut(index.unwrap()).left = box new_branch;
|
||||
}
|
||||
return (Node::new_branch(self.clone().elts,
|
||||
self.clone().rightmost_child),
|
||||
true);
|
||||
}
|
||||
//If we have a new branch node, attempt to insert it into the tree
|
||||
//as with the key-value pair, then check to see if the node is overfull.
|
||||
BranchNode(branch) => {
|
||||
let new_elt = branch.elts[0].clone();
|
||||
let new_elt_index = self.bsearch_branch(new_elt.clone().key);
|
||||
match new_elt_index {
|
||||
None => {
|
||||
return (Node::new_branch(self.clone().elts,
|
||||
self.clone().rightmost_child),
|
||||
false);
|
||||
}
|
||||
Some(i) => {
|
||||
self.elts.insert(i, new_elt);
|
||||
if i + 1 >= self.elts.len() {
|
||||
self.rightmost_child = branch.clone().rightmost_child;
|
||||
}
|
||||
else {
|
||||
self.elts.get_mut(i + 1).left =
|
||||
branch.clone().rightmost_child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//If the current node is overfilled, create a new branch with one element
|
||||
//and two children.
|
||||
if self.elts.len() > ub {
|
||||
let midpoint = self.elts.remove(ub / 2).unwrap();
|
||||
let (new_left, new_right) = self.clone().elts.partition(|le|
|
||||
midpoint.key.cmp(&le.key)
|
||||
== Greater);
|
||||
new_branch = Node::new_branch(
|
||||
vec!(BranchElt::new(midpoint.clone().key,
|
||||
midpoint.clone().value,
|
||||
box Node::new_branch(new_left,
|
||||
midpoint.clone().left))),
|
||||
box Node::new_branch(new_right, self.clone().rightmost_child));
|
||||
return (new_branch, true);
|
||||
}
|
||||
}
|
||||
(Node::new_branch(self.elts.clone(), self.rightmost_child.clone()), outcome)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for Branch<K, V> {
|
||||
/// Returns a new branch using the clone methods of the `Branch`'s internal variables.
|
||||
fn clone(&self) -> Branch<K, V> {
|
||||
Branch::new(self.elts.clone(), self.rightmost_child.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialEq for Branch<K, V> {
|
||||
fn eq(&self, other: &Branch<K, V>) -> bool {
|
||||
self.elts == other.elts
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for Branch<K, V> {}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for Branch<K, V> {
|
||||
fn partial_cmp(&self, other: &Branch<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for Branch<K, V> {
|
||||
/// Compares the first elements of two `Branch`es to determine an
|
||||
/// `Ordering`.
|
||||
fn cmp(&self, other: &Branch<K, V>) -> 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<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for Branch<K, V> {
|
||||
/// Returns a string representation of a `Branch`.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for (i, s) in self.elts.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, " // ")) }
|
||||
try!(write!(f, "{}", *s))
|
||||
}
|
||||
write!(f, " // rightmost child: ({}) ", *self.rightmost_child)
|
||||
}
|
||||
}
|
||||
|
||||
//A LeafElt contains no left child, but a key-value pair.
|
||||
struct LeafElt<K, V> {
|
||||
key: K,
|
||||
value: V
|
||||
}
|
||||
|
||||
//A BranchElt has a left child in insertion to a key-value pair.
|
||||
struct BranchElt<K, V> {
|
||||
left: Box<Node<K, V>>,
|
||||
key: K,
|
||||
value: V
|
||||
}
|
||||
|
||||
impl<K: Ord, V> LeafElt<K, V> {
|
||||
/// Creates a new `LeafElt` from a supplied key-value pair.
|
||||
fn new(k: K, v: V) -> LeafElt<K, V> {
|
||||
LeafElt {
|
||||
key: k,
|
||||
value: v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for LeafElt<K, V> {
|
||||
/// Returns a new `LeafElt` by cloning the key and value.
|
||||
fn clone(&self) -> LeafElt<K, V> {
|
||||
LeafElt::new(self.key.clone(), self.value.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialEq for LeafElt<K, V> {
|
||||
fn eq(&self, other: &LeafElt<K, V>) -> bool {
|
||||
self.key == other.key && self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for LeafElt<K, V> {}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for LeafElt<K, V> {
|
||||
fn partial_cmp(&self, other: &LeafElt<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for LeafElt<K, V> {
|
||||
/// Returns an ordering based on the keys of the `LeafElt`s.
|
||||
fn cmp(&self, other: &LeafElt<K, V>) -> Ordering {
|
||||
self.key.cmp(&other.key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for LeafElt<K, V> {
|
||||
/// Returns a string representation of a `LeafElt`.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Key: {}, value: {};", self.key, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V> BranchElt<K, V> {
|
||||
/// Creates a new `BranchElt` from a supplied key, value, and left child.
|
||||
fn new(k: K, v: V, n: Box<Node<K, V>>) -> BranchElt<K, V> {
|
||||
BranchElt {
|
||||
left: n,
|
||||
key: k,
|
||||
value: v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<K: Clone + Ord, V: Clone> Clone for BranchElt<K, V> {
|
||||
/// Returns a new `BranchElt` by cloning the key, value, and left child.
|
||||
fn clone(&self) -> BranchElt<K, V> {
|
||||
BranchElt::new(self.key.clone(),
|
||||
self.value.clone(),
|
||||
self.left.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialEq for BranchElt<K, V>{
|
||||
fn eq(&self, other: &BranchElt<K, V>) -> bool {
|
||||
self.key == other.key && self.value == other.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Eq for BranchElt<K, V>{}
|
||||
|
||||
impl<K: Ord, V: Eq> PartialOrd for BranchElt<K, V> {
|
||||
fn partial_cmp(&self, other: &BranchElt<K, V>) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V: Eq> Ord for BranchElt<K, V> {
|
||||
/// Fulfills `Ord` for `BranchElts`.
|
||||
fn cmp(&self, other: &BranchElt<K, V>) -> Ordering {
|
||||
self.key.cmp(&other.key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: fmt::Show + Ord, V: fmt::Show> fmt::Show for BranchElt<K, V> {
|
||||
/// Formats as a string containing the key, value, and child (which should recur to a
|
||||
/// leaf). Consider changing in future to be more readable.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Key: {}, value: {}, (child: {})",
|
||||
self.key, self.value, *self.left)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_btree {
|
||||
use std::prelude::*;
|
||||
|
||||
use super::{BTree, Node, LeafElt};
|
||||
|
||||
use MutableSeq;
|
||||
|
||||
//Tests the functionality of the insert methods (which are unfinished).
|
||||
#[test]
|
||||
fn insert_test_one() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2);
|
||||
let is_insert = b.insert(2i, "xyz".to_string());
|
||||
assert!(is_insert.root.is_leaf());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_test_two() {
|
||||
let leaf_elt_1 = LeafElt::new(1i, "aaa".to_string());
|
||||
let leaf_elt_2 = LeafElt::new(2i, "bbb".to_string());
|
||||
let leaf_elt_3 = LeafElt::new(3i, "ccc".to_string());
|
||||
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3));
|
||||
let b = BTree::new_with_node_len(n, 3, 2);
|
||||
//println!("{}", b.clone().insert(4, "ddd".to_string()).to_string());
|
||||
assert!(b.insert(4, "ddd".to_string()).root.is_leaf());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_test_three() {
|
||||
let leaf_elt_1 = LeafElt::new(1i, "aaa".to_string());
|
||||
let leaf_elt_2 = LeafElt::new(2i, "bbb".to_string());
|
||||
let leaf_elt_3 = LeafElt::new(3i, "ccc".to_string());
|
||||
let leaf_elt_4 = LeafElt::new(4i, "ddd".to_string());
|
||||
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3, leaf_elt_4));
|
||||
let b = BTree::new_with_node_len(n, 3, 2);
|
||||
//println!("{}", b.clone().insert(5, "eee".to_string()).to_string());
|
||||
assert!(!b.insert(5, "eee".to_string()).root.is_leaf());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_test_four() {
|
||||
let leaf_elt_1 = LeafElt::new(1i, "aaa".to_string());
|
||||
let leaf_elt_2 = LeafElt::new(2i, "bbb".to_string());
|
||||
let leaf_elt_3 = LeafElt::new(3i, "ccc".to_string());
|
||||
let leaf_elt_4 = LeafElt::new(4i, "ddd".to_string());
|
||||
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3, leaf_elt_4));
|
||||
let mut b = BTree::new_with_node_len(n, 3, 2);
|
||||
b = b.clone().insert(5, "eee".to_string());
|
||||
b = b.clone().insert(6, "fff".to_string());
|
||||
b = b.clone().insert(7, "ggg".to_string());
|
||||
b = b.clone().insert(8, "hhh".to_string());
|
||||
b = b.clone().insert(0, "omg".to_string());
|
||||
//println!("{}", b.clone().to_string());
|
||||
assert!(!b.root.is_leaf());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bsearch_test_one() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2u);
|
||||
assert_eq!(Some(1), b.root.bsearch_node(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bsearch_test_two() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2u);
|
||||
assert_eq!(Some(0), b.root.bsearch_node(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bsearch_test_three() {
|
||||
let leaf_elt_1 = LeafElt::new(1i, "aaa".to_string());
|
||||
let leaf_elt_2 = LeafElt::new(2i, "bbb".to_string());
|
||||
let leaf_elt_3 = LeafElt::new(4i, "ccc".to_string());
|
||||
let leaf_elt_4 = LeafElt::new(5i, "ddd".to_string());
|
||||
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3, leaf_elt_4));
|
||||
let b = BTree::new_with_node_len(n, 3, 2);
|
||||
assert_eq!(Some(2), b.root.bsearch_node(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bsearch_test_four() {
|
||||
let leaf_elt_1 = LeafElt::new(1i, "aaa".to_string());
|
||||
let leaf_elt_2 = LeafElt::new(2i, "bbb".to_string());
|
||||
let leaf_elt_3 = LeafElt::new(4i, "ccc".to_string());
|
||||
let leaf_elt_4 = LeafElt::new(5i, "ddd".to_string());
|
||||
let n = Node::new_leaf(vec!(leaf_elt_1, leaf_elt_2, leaf_elt_3, leaf_elt_4));
|
||||
let b = BTree::new_with_node_len(n, 3, 2);
|
||||
assert_eq!(Some(4), b.root.bsearch_node(800));
|
||||
}
|
||||
|
||||
//Tests the functionality of the get method.
|
||||
#[test]
|
||||
fn get_test() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2);
|
||||
let val = b.get(1);
|
||||
assert_eq!(val, Some("abc".to_string()));
|
||||
}
|
||||
|
||||
//Tests the BTree's clone() method.
|
||||
#[test]
|
||||
fn btree_clone_test() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2);
|
||||
let b2 = b.clone();
|
||||
assert!(b.root == 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(1i, "abc".to_string(), 2);
|
||||
let b2 = BTree::new(2i, "bcd".to_string(), 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(1i, "abc".to_string(), 2);
|
||||
let b2 = BTree::new(1i, "bcd".to_string(), 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(1i, "abc".to_string(), 2);
|
||||
let b2 = BTree::new(2i, "bcd".to_string(), 2);
|
||||
assert!(&b2.cmp(&b) == &Greater)
|
||||
}
|
||||
|
||||
//Tests the BTree's to_string() method.
|
||||
#[test]
|
||||
fn btree_tostr_test() {
|
||||
let b = BTree::new(1i, "abc".to_string(), 2);
|
||||
assert_eq!(b.to_string(), "Key: 1, value: abc;".to_string())
|
||||
}
|
||||
|
||||
}
|
1203
src/libcollections/btree/map.rs
Normal file
1203
src/libcollections/btree/map.rs
Normal file
File diff suppressed because it is too large
Load Diff
32
src/libcollections/btree/mod.rs
Normal file
32
src/libcollections/btree/mod.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub use self::map::BTreeMap;
|
||||
pub use self::map::Entries;
|
||||
pub use self::map::MutEntries;
|
||||
pub use self::map::MoveEntries;
|
||||
pub use self::map::Keys;
|
||||
pub use self::map::Values;
|
||||
pub use self::map::Entry;
|
||||
pub use self::map::OccupiedEntry;
|
||||
pub use self::map::VacantEntry;
|
||||
|
||||
pub use self::set::BTreeSet;
|
||||
pub use self::set::Items;
|
||||
pub use self::set::MoveItems;
|
||||
pub use self::set::DifferenceItems;
|
||||
pub use self::set::UnionItems;
|
||||
pub use self::set::SymDifferenceItems;
|
||||
pub use self::set::IntersectionItems;
|
||||
|
||||
|
||||
mod node;
|
||||
mod map;
|
||||
mod set;
|
552
src/libcollections/btree/node.rs
Normal file
552
src/libcollections/btree/node.rs
Normal file
@ -0,0 +1,552 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This module represents all the internal representation and logic for a B-Tree's node
|
||||
// with a safe interface, so that BTreeMap itself does not depend on any of these details.
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::{slice, mem, ptr};
|
||||
use core::iter::Zip;
|
||||
use MutableSeq;
|
||||
|
||||
use vec;
|
||||
use vec::Vec;
|
||||
|
||||
/// Represents the result of an Insertion: either the item fit, or the node had to split
|
||||
pub enum InsertionResult<K, V> {
|
||||
/// The inserted element fit
|
||||
Fit,
|
||||
/// The inserted element did not fit, so the node was split
|
||||
Split(K, V, Node<K, V>),
|
||||
}
|
||||
|
||||
/// Represents the result of a search for a key in a single node
|
||||
pub enum SearchResult {
|
||||
/// The element was found at the given index
|
||||
Found(uint),
|
||||
/// The element wasn't found, but if it's anywhere, it must be beyond this edge
|
||||
GoDown(uint),
|
||||
}
|
||||
|
||||
/// A B-Tree Node. We keep keys/edges/values separate to optimize searching for keys.
|
||||
#[deriving(Clone)]
|
||||
pub struct Node<K, V> {
|
||||
// FIXME(Gankro): This representation is super safe and easy to reason about, but painfully
|
||||
// inefficient. As three Vecs, each node consists of *9* words: (ptr, cap, size) * 3. In
|
||||
// theory, if we take full control of allocation like HashMap's RawTable does,
|
||||
// and restrict leaves to max size 256 (not unreasonable for a btree node) we can cut
|
||||
// this down to just (ptr, cap: u8, size: u8, is_leaf: bool). With generic
|
||||
// integer arguments, cap can even move into the the type, reducing this just to
|
||||
// (ptr, size, is_leaf). This could also have cache benefits for very small nodes, as keys
|
||||
// could bleed into edges and vals.
|
||||
//
|
||||
// However doing this would require a fair amount of code to reimplement all
|
||||
// the Vec logic and iterators. It would also use *way* more unsafe code, which sucks and is
|
||||
// hard. For now, we accept this cost in the name of correctness and simplicity.
|
||||
//
|
||||
// As a compromise, keys and vals could be merged into one Vec<(K, V)>, which would shave
|
||||
// off 3 words, but possibly hurt our cache effeciency during search, which only cares about
|
||||
// keys. This would also avoid the Zip we use in our iterator implementations. This is
|
||||
// probably worth investigating.
|
||||
//
|
||||
// Note that this space waste is especially tragic since we store the Nodes by value in their
|
||||
// parent's edges Vec, so unoccupied spaces in the edges Vec are quite large, and we have
|
||||
// to shift around a lot more bits during insertion/removal.
|
||||
|
||||
keys: Vec<K>,
|
||||
edges: Vec<Node<K, V>>,
|
||||
vals: Vec<V>,
|
||||
}
|
||||
|
||||
impl<K: Ord, V> Node<K, V> {
|
||||
/// Searches for the given key in the node. If it finds an exact match,
|
||||
/// `Found` will be yielded with the matching index. If it fails to find an exact match,
|
||||
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
|
||||
pub fn search(&self, key: &K) -> SearchResult {
|
||||
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
|
||||
// For the B configured as of this writing (B = 6), binary search was *singnificantly*
|
||||
// worse for uints.
|
||||
self.search_linear(key)
|
||||
}
|
||||
|
||||
fn search_linear(&self, key: &K) -> SearchResult {
|
||||
for (i, k) in self.keys.iter().enumerate() {
|
||||
match k.cmp(key) {
|
||||
Less => {},
|
||||
Equal => return Found(i),
|
||||
Greater => return GoDown(i),
|
||||
}
|
||||
}
|
||||
GoDown(self.len())
|
||||
}
|
||||
}
|
||||
|
||||
// Public interface
|
||||
impl <K, V> Node<K, V> {
|
||||
/// Make a new internal node
|
||||
pub fn new_internal(capacity: uint) -> Node<K, V> {
|
||||
Node {
|
||||
keys: Vec::with_capacity(capacity),
|
||||
vals: Vec::with_capacity(capacity),
|
||||
edges: Vec::with_capacity(capacity + 1),
|
||||
}
|
||||
}
|
||||
|
||||
/// Make a new leaf node
|
||||
pub fn new_leaf(capacity: uint) -> Node<K, V> {
|
||||
Node {
|
||||
keys: Vec::with_capacity(capacity),
|
||||
vals: Vec::with_capacity(capacity),
|
||||
edges: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Make a leaf root from scratch
|
||||
pub fn make_leaf_root(b: uint) -> Node<K, V> {
|
||||
Node::new_leaf(capacity_from_b(b))
|
||||
}
|
||||
|
||||
/// Make an internal root and swap it with an old root
|
||||
pub fn make_internal_root(left_and_out: &mut Node<K,V>, b: uint, key: K, value: V,
|
||||
right: Node<K,V>) {
|
||||
let mut node = Node::new_internal(capacity_from_b(b));
|
||||
mem::swap(left_and_out, &mut node);
|
||||
left_and_out.keys.push(key);
|
||||
left_and_out.vals.push(value);
|
||||
left_and_out.edges.push(node);
|
||||
left_and_out.edges.push(right);
|
||||
}
|
||||
|
||||
|
||||
/// How many key-value pairs the node contains
|
||||
pub fn len(&self) -> uint {
|
||||
self.keys.len()
|
||||
}
|
||||
|
||||
/// How many key-value pairs the node can fit
|
||||
pub fn capacity(&self) -> uint {
|
||||
self.keys.capacity()
|
||||
}
|
||||
|
||||
/// If the node has any children
|
||||
pub fn is_leaf(&self) -> bool {
|
||||
self.edges.is_empty()
|
||||
}
|
||||
|
||||
/// if the node has too few elements
|
||||
pub fn is_underfull(&self) -> bool {
|
||||
self.len() < min_load_from_capacity(self.capacity())
|
||||
}
|
||||
|
||||
/// if the node cannot fit any more elements
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.len() == self.capacity()
|
||||
}
|
||||
|
||||
/// Swap the given key-value pair with the key-value pair stored in the node's index,
|
||||
/// without checking bounds.
|
||||
pub unsafe fn unsafe_swap(&mut self, index: uint, key: &mut K, val: &mut V) {
|
||||
mem::swap(self.keys.as_mut_slice().unsafe_mut(index), key);
|
||||
mem::swap(self.vals.as_mut_slice().unsafe_mut(index), val);
|
||||
}
|
||||
|
||||
/// Get the node's key mutably without any bounds checks.
|
||||
pub unsafe fn unsafe_key_mut(&mut self, index: uint) -> &mut K {
|
||||
self.keys.as_mut_slice().unsafe_mut(index)
|
||||
}
|
||||
|
||||
/// Get the node's value at the given index
|
||||
pub fn val(&self, index: uint) -> Option<&V> {
|
||||
self.vals.as_slice().get(index)
|
||||
}
|
||||
|
||||
/// Get the node's value at the given index
|
||||
pub fn val_mut(&mut self, index: uint) -> Option<&mut V> {
|
||||
self.vals.as_mut_slice().get_mut(index)
|
||||
}
|
||||
|
||||
/// Get the node's value mutably without any bounds checks.
|
||||
pub unsafe fn unsafe_val_mut(&mut self, index: uint) -> &mut V {
|
||||
self.vals.as_mut_slice().unsafe_mut(index)
|
||||
}
|
||||
|
||||
/// Get the node's edge at the given index
|
||||
pub fn edge(&self, index: uint) -> Option<&Node<K,V>> {
|
||||
self.edges.as_slice().get(index)
|
||||
}
|
||||
|
||||
/// Get the node's edge mutably at the given index
|
||||
pub fn edge_mut(&mut self, index: uint) -> Option<&mut Node<K,V>> {
|
||||
self.edges.as_mut_slice().get_mut(index)
|
||||
}
|
||||
|
||||
/// Get the node's edge mutably without any bounds checks.
|
||||
pub unsafe fn unsafe_edge_mut(&mut self, index: uint) -> &mut Node<K,V> {
|
||||
self.edges.as_mut_slice().unsafe_mut(index)
|
||||
}
|
||||
|
||||
/// Pop an edge off the end of the node
|
||||
pub fn pop_edge(&mut self) -> Option<Node<K,V>> {
|
||||
self.edges.pop()
|
||||
}
|
||||
|
||||
/// Try to insert this key-value pair at the given index in this internal node
|
||||
/// If the node is full, we have to split it.
|
||||
///
|
||||
/// Returns a *mut V to the inserted value, because the caller may want this when
|
||||
/// they're done mutating the tree, but we don't want to borrow anything for now.
|
||||
pub fn insert_as_leaf(&mut self, index: uint, key: K, value: V) ->
|
||||
(InsertionResult<K, V>, *mut V) {
|
||||
if !self.is_full() {
|
||||
// The element can fit, just insert it
|
||||
self.insert_fit_as_leaf(index, key, value);
|
||||
(Fit, unsafe { self.unsafe_val_mut(index) as *mut _ })
|
||||
} else {
|
||||
// The element can't fit, this node is full. Split it into two nodes.
|
||||
let (new_key, new_val, mut new_right) = self.split();
|
||||
let left_len = self.len();
|
||||
|
||||
let ptr = if index <= left_len {
|
||||
self.insert_fit_as_leaf(index, key, value);
|
||||
unsafe { self.unsafe_val_mut(index) as *mut _ }
|
||||
} else {
|
||||
new_right.insert_fit_as_leaf(index - left_len - 1, key, value);
|
||||
unsafe { new_right.unsafe_val_mut(index - left_len - 1) as *mut _ }
|
||||
};
|
||||
|
||||
(Split(new_key, new_val, new_right), ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to insert this key-value pair at the given index in this internal node
|
||||
/// If the node is full, we have to split it.
|
||||
pub fn insert_as_internal(&mut self, index: uint, key: K, value: V, right: Node<K, V>)
|
||||
-> InsertionResult<K, V> {
|
||||
if !self.is_full() {
|
||||
// The element can fit, just insert it
|
||||
self.insert_fit_as_internal(index, key, value, right);
|
||||
Fit
|
||||
} else {
|
||||
// The element can't fit, this node is full. Split it into two nodes.
|
||||
let (new_key, new_val, mut new_right) = self.split();
|
||||
let left_len = self.len();
|
||||
|
||||
if index <= left_len {
|
||||
self.insert_fit_as_internal(index, key, value, right);
|
||||
} else {
|
||||
new_right.insert_fit_as_internal(index - left_len - 1, key, value, right);
|
||||
}
|
||||
|
||||
Split(new_key, new_val, new_right)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the key-value pair at the given index
|
||||
pub fn remove_as_leaf(&mut self, index: uint) -> (K, V) {
|
||||
match (self.keys.remove(index), self.vals.remove(index)) {
|
||||
(Some(k), Some(v)) => (k, v),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle an underflow in this node's child. We favour handling "to the left" because we know
|
||||
/// we're empty, but our neighbour can be full. Handling to the left means when we choose to
|
||||
/// steal, we pop off the end of our neighbour (always fast) and "unshift" ourselves
|
||||
/// (always slow, but at least faster since we know we're half-empty).
|
||||
/// Handling "to the right" reverses these roles. Of course, we merge whenever possible
|
||||
/// because we want dense nodes, and merging is about equal work regardless of direction.
|
||||
pub fn handle_underflow(&mut self, underflowed_child_index: uint) {
|
||||
assert!(underflowed_child_index <= self.len());
|
||||
unsafe {
|
||||
if underflowed_child_index > 0 {
|
||||
self.handle_underflow_to_left(underflowed_child_index);
|
||||
} else {
|
||||
self.handle_underflow_to_right(underflowed_child_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter<'a>(&'a self) -> Traversal<'a, K, V> {
|
||||
let is_leaf = self.is_leaf();
|
||||
Traversal {
|
||||
elems: self.keys.as_slice().iter().zip(self.vals.as_slice().iter()),
|
||||
edges: self.edges.as_slice().iter(),
|
||||
head_is_edge: true,
|
||||
tail_is_edge: true,
|
||||
has_edges: !is_leaf,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_mut<'a>(&'a mut self) -> MutTraversal<'a, K, V> {
|
||||
let is_leaf = self.is_leaf();
|
||||
MutTraversal {
|
||||
elems: self.keys.as_slice().iter().zip(self.vals.as_mut_slice().iter_mut()),
|
||||
edges: self.edges.as_mut_slice().iter_mut(),
|
||||
head_is_edge: true,
|
||||
tail_is_edge: true,
|
||||
has_edges: !is_leaf,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_iter(self) -> MoveTraversal<K, V> {
|
||||
let is_leaf = self.is_leaf();
|
||||
MoveTraversal {
|
||||
elems: self.keys.into_iter().zip(self.vals.into_iter()),
|
||||
edges: self.edges.into_iter(),
|
||||
head_is_edge: true,
|
||||
tail_is_edge: true,
|
||||
has_edges: !is_leaf,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Private implementation details
|
||||
impl<K, V> Node<K, V> {
|
||||
/// Make a node from its raw components
|
||||
fn from_vecs(keys: Vec<K>, vals: Vec<V>, edges: Vec<Node<K, V>>) -> Node<K, V> {
|
||||
Node {
|
||||
keys: keys,
|
||||
vals: vals,
|
||||
edges: edges,
|
||||
}
|
||||
}
|
||||
|
||||
/// We have somehow verified that this key-value pair will fit in this internal node,
|
||||
/// so insert under that assumption.
|
||||
fn insert_fit_as_leaf(&mut self, index: uint, key: K, val: V) {
|
||||
self.keys.insert(index, key);
|
||||
self.vals.insert(index, val);
|
||||
}
|
||||
|
||||
/// We have somehow verified that this key-value pair will fit in this internal node,
|
||||
/// so insert under that assumption
|
||||
fn insert_fit_as_internal(&mut self, index: uint, key: K, val: V, right: Node<K, V>) {
|
||||
self.keys.insert(index, key);
|
||||
self.vals.insert(index, val);
|
||||
self.edges.insert(index + 1, right);
|
||||
}
|
||||
|
||||
/// Node is full, so split it into two nodes, and yield the middle-most key-value pair
|
||||
/// because we have one too many, and our parent now has one too few
|
||||
fn split(&mut self) -> (K, V, Node<K, V>) {
|
||||
let r_keys = split(&mut self.keys);
|
||||
let r_vals = split(&mut self.vals);
|
||||
let r_edges = if self.edges.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
split(&mut self.edges)
|
||||
};
|
||||
|
||||
let right = Node::from_vecs(r_keys, r_vals, r_edges);
|
||||
// Pop it
|
||||
let key = self.keys.pop().unwrap();
|
||||
let val = self.vals.pop().unwrap();
|
||||
|
||||
(key, val, right)
|
||||
}
|
||||
|
||||
/// Right is underflowed. Try to steal from left,
|
||||
/// but merge left and right if left is low too.
|
||||
unsafe fn handle_underflow_to_left(&mut self, underflowed_child_index: uint) {
|
||||
let left_len = self.edges[underflowed_child_index - 1].len();
|
||||
if left_len > min_load_from_capacity(self.capacity()) {
|
||||
self.steal_to_left(underflowed_child_index);
|
||||
} else {
|
||||
self.merge_children(underflowed_child_index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Left is underflowed. Try to steal from the right,
|
||||
/// but merge left and right if right is low too.
|
||||
unsafe fn handle_underflow_to_right(&mut self, underflowed_child_index: uint) {
|
||||
let right_len = self.edges[underflowed_child_index + 1].len();
|
||||
if right_len > min_load_from_capacity(self.capacity()) {
|
||||
self.steal_to_right(underflowed_child_index);
|
||||
} else {
|
||||
self.merge_children(underflowed_child_index);
|
||||
}
|
||||
}
|
||||
|
||||
/// Steal! Stealing is roughly analagous to a binary tree rotation.
|
||||
/// In this case, we're "rotating" right.
|
||||
unsafe fn steal_to_left(&mut self, underflowed_child_index: uint) {
|
||||
// Take the biggest stuff off left
|
||||
let (mut key, mut val, edge) = {
|
||||
let left = self.unsafe_edge_mut(underflowed_child_index - 1);
|
||||
match (left.keys.pop(), left.vals.pop(), left.edges.pop()) {
|
||||
(Some(k), Some(v), e) => (k, v, e),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
// Swap the parent's seperating key-value pair with left's
|
||||
self.unsafe_swap(underflowed_child_index - 1, &mut key, &mut val);
|
||||
|
||||
// Put them at the start of right
|
||||
{
|
||||
let right = self.unsafe_edge_mut(underflowed_child_index);
|
||||
right.keys.insert(0, key);
|
||||
right.vals.insert(0, val);
|
||||
match edge {
|
||||
None => {}
|
||||
Some(e) => right.edges.insert(0, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Steal! Stealing is roughly analagous to a binary tree rotation.
|
||||
/// In this case, we're "rotating" left.
|
||||
unsafe fn steal_to_right(&mut self, underflowed_child_index: uint) {
|
||||
// Take the smallest stuff off right
|
||||
let (mut key, mut val, edge) = {
|
||||
let right = self.unsafe_edge_mut(underflowed_child_index + 1);
|
||||
match (right.keys.remove(0), right.vals.remove(0), right.edges.remove(0)) {
|
||||
(Some(k), Some(v), e) => (k, v, e),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
// Swap the parent's seperating key-value pair with right's
|
||||
self.unsafe_swap(underflowed_child_index, &mut key, &mut val);
|
||||
|
||||
// Put them at the end of left
|
||||
{
|
||||
let left = self.unsafe_edge_mut(underflowed_child_index);
|
||||
left.keys.push(key);
|
||||
left.vals.push(val);
|
||||
match edge {
|
||||
None => {}
|
||||
Some(e) => left.edges.push(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge! Left and right will be smooshed into one node, along with the key-value
|
||||
/// pair that seperated them in their parent.
|
||||
unsafe fn merge_children(&mut self, left_index: uint) {
|
||||
// Permanently remove right's index, and the key-value pair that seperates
|
||||
// left and right
|
||||
let (key, val, right) = {
|
||||
match (self.keys.remove(left_index),
|
||||
self.vals.remove(left_index),
|
||||
self.edges.remove(left_index + 1)) {
|
||||
(Some(k), Some(v), Some(e)) => (k, v, e),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
// Give left right's stuff.
|
||||
let left = self.unsafe_edge_mut(left_index);
|
||||
left.absorb(key, val, right);
|
||||
}
|
||||
|
||||
/// Take all the values from right, seperated by the given key and value
|
||||
fn absorb(&mut self, key: K, val: V, right: Node<K, V>) {
|
||||
// Just as a sanity check, make sure we can fit this guy in
|
||||
debug_assert!(self.len() + right.len() <= self.capacity())
|
||||
|
||||
self.keys.push(key);
|
||||
self.vals.push(val);
|
||||
self.keys.extend(right.keys.into_iter());
|
||||
self.vals.extend(right.vals.into_iter());
|
||||
self.edges.extend(right.edges.into_iter());
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a Vec, and splits half the elements into a new one.
|
||||
fn split<T>(left: &mut Vec<T>) -> Vec<T> {
|
||||
// This function is intended to be called on a full Vec of size 2B - 1 (keys, values),
|
||||
// or 2B (edges). In the former case, left should get B elements, and right should get
|
||||
// B - 1. In the latter case, both should get B. Therefore, we can just always take the last
|
||||
// size / 2 elements from left, and put them on right. This also ensures this method is
|
||||
// safe, even if the Vec isn't full. Just uninteresting for our purposes.
|
||||
let len = left.len();
|
||||
let right_len = len / 2;
|
||||
let left_len = len - right_len;
|
||||
let mut right = Vec::with_capacity(left.capacity());
|
||||
unsafe {
|
||||
let left_ptr = left.as_slice().unsafe_get(left_len) as *const _;
|
||||
let right_ptr = right.as_mut_slice().as_mut_ptr();
|
||||
ptr::copy_nonoverlapping_memory(right_ptr, left_ptr, right_len);
|
||||
left.set_len(left_len);
|
||||
right.set_len(right_len);
|
||||
}
|
||||
right
|
||||
}
|
||||
|
||||
/// Get the capacity of a node from the order of the parent B-Tree
|
||||
fn capacity_from_b(b: uint) -> uint {
|
||||
2 * b - 1
|
||||
}
|
||||
|
||||
/// Get the minimum load of a node from its capacity
|
||||
fn min_load_from_capacity(cap: uint) -> uint {
|
||||
// B - 1
|
||||
cap / 2
|
||||
}
|
||||
|
||||
/// An abstraction over all the different kinds of traversals a node supports
|
||||
struct AbsTraversal<Elems, Edges> {
|
||||
elems: Elems,
|
||||
edges: Edges,
|
||||
head_is_edge: bool,
|
||||
tail_is_edge: bool,
|
||||
has_edges: bool,
|
||||
}
|
||||
|
||||
/// A single atomic step in a traversal. Either an element is visited, or an edge is followed
|
||||
pub enum TraversalItem<K, V, E> {
|
||||
Elem(K, V),
|
||||
Edge(E),
|
||||
}
|
||||
|
||||
/// A traversal over a node's entries and edges
|
||||
pub type Traversal<'a, K, V> = AbsTraversal<Zip<slice::Items<'a, K>, slice::Items<'a, V>>,
|
||||
slice::Items<'a, Node<K, V>>>;
|
||||
|
||||
/// A mutable traversal over a node's entries and edges
|
||||
pub type MutTraversal<'a, K, V> = AbsTraversal<Zip<slice::Items<'a, K>, slice::MutItems<'a, V>>,
|
||||
slice::MutItems<'a, Node<K, V>>>;
|
||||
|
||||
/// An owning traversal over a node's entries and edges
|
||||
pub type MoveTraversal<K, V> = AbsTraversal<Zip<vec::MoveItems<K>, vec::MoveItems<V>>,
|
||||
vec::MoveItems<Node<K, V>>>;
|
||||
|
||||
|
||||
impl<K, V, E, Elems: Iterator<(K, V)>, Edges: Iterator<E>>
|
||||
Iterator<TraversalItem<K, V, E>> for AbsTraversal<Elems, Edges> {
|
||||
|
||||
fn next(&mut self) -> Option<TraversalItem<K, V, E>> {
|
||||
let head_is_edge = self.head_is_edge;
|
||||
self.head_is_edge = !head_is_edge;
|
||||
|
||||
if head_is_edge && self.has_edges {
|
||||
self.edges.next().map(|node| Edge(node))
|
||||
} else {
|
||||
self.elems.next().map(|(k, v)| Elem(k, v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, E, Elems: DoubleEndedIterator<(K, V)>, Edges: DoubleEndedIterator<E>>
|
||||
DoubleEndedIterator<TraversalItem<K, V, E>> for AbsTraversal<Elems, Edges> {
|
||||
|
||||
fn next_back(&mut self) -> Option<TraversalItem<K, V, E>> {
|
||||
let tail_is_edge = self.tail_is_edge;
|
||||
self.tail_is_edge = !tail_is_edge;
|
||||
|
||||
if tail_is_edge && self.has_edges {
|
||||
self.edges.next_back().map(|node| Edge(node))
|
||||
} else {
|
||||
self.elems.next_back().map(|(k, v)| Elem(k, v))
|
||||
}
|
||||
}
|
||||
}
|
433
src/libcollections/btree/set.rs
Normal file
433
src/libcollections/btree/set.rs
Normal file
@ -0,0 +1,433 @@
|
||||
// Copyright 2014 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface
|
||||
// to TreeMap
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use super::{BTreeMap, Keys, MoveEntries};
|
||||
use std::hash::Hash;
|
||||
use core::default::Default;
|
||||
use core::{iter, fmt};
|
||||
use core::iter::Peekable;
|
||||
use core::fmt::Show;
|
||||
|
||||
use {Mutable, Set, MutableSet, MutableMap, Map};
|
||||
|
||||
/// A set based on a B-Tree.
|
||||
#[deriving(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct BTreeSet<T>{
|
||||
map: BTreeMap<T, ()>,
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeSet's items.
|
||||
pub type Items<'a, T> = Keys<'a, T, ()>;
|
||||
|
||||
/// An owning iterator over a BTreeSet's items.
|
||||
pub type MoveItems<T> = iter::Map<'static, (T, ()), T, MoveEntries<T, ()>>;
|
||||
|
||||
/// A lazy iterator producing elements in the set difference (in-order).
|
||||
pub struct DifferenceItems<'a, T:'a> {
|
||||
a: Peekable<&'a T, Items<'a, T>>,
|
||||
b: Peekable<&'a T, Items<'a, T>>,
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set symmetric difference (in-order).
|
||||
pub struct SymDifferenceItems<'a, T:'a> {
|
||||
a: Peekable<&'a T, Items<'a, T>>,
|
||||
b: Peekable<&'a T, Items<'a, T>>,
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set intersection (in-order).
|
||||
pub struct IntersectionItems<'a, T:'a> {
|
||||
a: Peekable<&'a T, Items<'a, T>>,
|
||||
b: Peekable<&'a T, Items<'a, T>>,
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set union (in-order).
|
||||
pub struct UnionItems<'a, T:'a> {
|
||||
a: Peekable<&'a T, Items<'a, T>>,
|
||||
b: Peekable<&'a T, Items<'a, T>>,
|
||||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Makes a new BTreeSet with a reasonable choice of B.
|
||||
pub fn new() -> BTreeSet<T> {
|
||||
BTreeSet { map: BTreeMap::new() }
|
||||
}
|
||||
|
||||
/// Makes a new BTreeSet with the given B.
|
||||
pub fn with_b(b: uint) -> BTreeSet<T> {
|
||||
BTreeSet { map: BTreeMap::with_b(b) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BTreeSet<T> {
|
||||
/// Gets an iterator over the BTreeSet's contents.
|
||||
pub fn iter<'a>(&'a self) -> Items<'a, T> {
|
||||
self.map.keys()
|
||||
}
|
||||
|
||||
/// Gets an iterator for moving out the BtreeSet's contents.
|
||||
pub fn into_iter(self) -> MoveItems<T> {
|
||||
self.map.into_iter().map(|(k, _)| k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Visits the values representing the difference, in ascending order.
|
||||
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> DifferenceItems<'a, T> {
|
||||
DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()}
|
||||
}
|
||||
|
||||
/// Visits the values representing the symmetric difference, in ascending order.
|
||||
pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
|
||||
-> SymDifferenceItems<'a, T> {
|
||||
SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()}
|
||||
}
|
||||
|
||||
/// Visits the values representing the intersection, in ascending order.
|
||||
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
|
||||
-> IntersectionItems<'a, T> {
|
||||
IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()}
|
||||
}
|
||||
|
||||
/// Visits the values representing the union, in ascending order.
|
||||
pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> UnionItems<'a, T> {
|
||||
UnionItems{a: self.iter().peekable(), b: other.iter().peekable()}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Collection for BTreeSet<T> {
|
||||
fn len(&self) -> uint {
|
||||
self.map.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Mutable for BTreeSet<T> {
|
||||
fn clear(&mut self) {
|
||||
self.map.clear()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Set<T> for BTreeSet<T> {
|
||||
fn contains(&self, value: &T) -> bool {
|
||||
self.map.find(value).is_some()
|
||||
}
|
||||
|
||||
fn is_disjoint(&self, other: &BTreeSet<T>) -> bool {
|
||||
self.intersection(other).next().is_none()
|
||||
}
|
||||
|
||||
fn is_subset(&self, other: &BTreeSet<T>) -> bool {
|
||||
// Stolen from TreeMap
|
||||
let mut x = self.iter();
|
||||
let mut y = other.iter();
|
||||
let mut a = x.next();
|
||||
let mut b = y.next();
|
||||
while a.is_some() {
|
||||
if b.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let a1 = a.unwrap();
|
||||
let b1 = b.unwrap();
|
||||
|
||||
match b1.cmp(a1) {
|
||||
Less => (),
|
||||
Greater => return false,
|
||||
Equal => a = x.next(),
|
||||
}
|
||||
|
||||
b = y.next();
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> MutableSet<T> for BTreeSet<T>{
|
||||
fn insert(&mut self, value: T) -> bool {
|
||||
self.map.insert(value, ())
|
||||
}
|
||||
|
||||
fn remove(&mut self, value: &T) -> bool {
|
||||
self.map.remove(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
|
||||
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> BTreeSet<T> {
|
||||
let mut set = BTreeSet::new();
|
||||
set.extend(iter);
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Extendable<T> for BTreeSet<T> {
|
||||
#[inline]
|
||||
fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
|
||||
for elem in iter {
|
||||
self.insert(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> Default for BTreeSet<T> {
|
||||
fn default() -> BTreeSet<T> {
|
||||
BTreeSet::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Show> Show for BTreeSet<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, x) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
try!(write!(f, "{}", *x));
|
||||
}
|
||||
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None
|
||||
fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
|
||||
short: Ordering, long: Ordering) -> Ordering {
|
||||
match (x, y) {
|
||||
(None , _ ) => short,
|
||||
(_ , None ) => long,
|
||||
(Some(x1), Some(y1)) => x1.cmp(y1),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> {
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => { self.a.next(); self.b.next(); }
|
||||
Greater => { self.b.next(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> {
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => { self.a.next(); self.b.next(); }
|
||||
Greater => return self.b.next(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> {
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
let o_cmp = match (self.a.peek(), self.b.peek()) {
|
||||
(None , _ ) => None,
|
||||
(_ , None ) => None,
|
||||
(Some(a1), Some(b1)) => Some(a1.cmp(b1)),
|
||||
};
|
||||
match o_cmp {
|
||||
None => return None,
|
||||
Some(Less) => { self.a.next(); }
|
||||
Some(Equal) => { self.b.next(); return self.a.next() }
|
||||
Some(Greater) => { self.b.next(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> {
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => { self.b.next(); return self.a.next() }
|
||||
Greater => return self.b.next(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::prelude::*;
|
||||
|
||||
use {Set, MutableSet};
|
||||
use super::BTreeSet;
|
||||
use std::hash;
|
||||
|
||||
#[test]
|
||||
fn test_clone_eq() {
|
||||
let mut m = BTreeSet::new();
|
||||
|
||||
m.insert(1i);
|
||||
m.insert(2);
|
||||
|
||||
assert!(m.clone() == m);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
let mut x = BTreeSet::new();
|
||||
let mut y = BTreeSet::new();
|
||||
|
||||
x.insert(1i);
|
||||
x.insert(2);
|
||||
x.insert(3);
|
||||
|
||||
y.insert(3i);
|
||||
y.insert(2);
|
||||
y.insert(1);
|
||||
|
||||
assert!(hash::hash(&x) == hash::hash(&y));
|
||||
}
|
||||
|
||||
fn check(a: &[int],
|
||||
b: &[int],
|
||||
expected: &[int],
|
||||
f: |&BTreeSet<int>, &BTreeSet<int>, f: |&int| -> bool| -> bool) {
|
||||
let mut set_a = BTreeSet::new();
|
||||
let mut set_b = BTreeSet::new();
|
||||
|
||||
for x in a.iter() { assert!(set_a.insert(*x)) }
|
||||
for y in b.iter() { assert!(set_b.insert(*y)) }
|
||||
|
||||
let mut i = 0;
|
||||
f(&set_a, &set_b, |x| {
|
||||
assert_eq!(*x, expected[i]);
|
||||
i += 1;
|
||||
true
|
||||
});
|
||||
assert_eq!(i, expected.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersection() {
|
||||
fn check_intersection(a: &[int], b: &[int], expected: &[int]) {
|
||||
check(a, b, expected, |x, y, f| x.intersection(y).all(f))
|
||||
}
|
||||
|
||||
check_intersection([], [], []);
|
||||
check_intersection([1, 2, 3], [], []);
|
||||
check_intersection([], [1, 2, 3], []);
|
||||
check_intersection([2], [1, 2, 3], [2]);
|
||||
check_intersection([1, 2, 3], [2], [2]);
|
||||
check_intersection([11, 1, 3, 77, 103, 5, -5],
|
||||
[2, 11, 77, -9, -42, 5, 3],
|
||||
[3, 5, 11, 77]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difference() {
|
||||
fn check_difference(a: &[int], b: &[int], expected: &[int]) {
|
||||
check(a, b, expected, |x, y, f| x.difference(y).all(f))
|
||||
}
|
||||
|
||||
check_difference([], [], []);
|
||||
check_difference([1, 12], [], [1, 12]);
|
||||
check_difference([], [1, 2, 3, 9], []);
|
||||
check_difference([1, 3, 5, 9, 11],
|
||||
[3, 9],
|
||||
[1, 5, 11]);
|
||||
check_difference([-5, 11, 22, 33, 40, 42],
|
||||
[-12, -5, 14, 23, 34, 38, 39, 50],
|
||||
[11, 22, 33, 40, 42]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_symmetric_difference() {
|
||||
fn check_symmetric_difference(a: &[int], b: &[int],
|
||||
expected: &[int]) {
|
||||
check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
|
||||
}
|
||||
|
||||
check_symmetric_difference([], [], []);
|
||||
check_symmetric_difference([1, 2, 3], [2], [1, 3]);
|
||||
check_symmetric_difference([2], [1, 2, 3], [1, 3]);
|
||||
check_symmetric_difference([1, 3, 5, 9, 11],
|
||||
[-2, 3, 9, 14, 22],
|
||||
[-2, 1, 5, 11, 14, 22]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union() {
|
||||
fn check_union(a: &[int], b: &[int],
|
||||
expected: &[int]) {
|
||||
check(a, b, expected, |x, y, f| x.union(y).all(f))
|
||||
}
|
||||
|
||||
check_union([], [], []);
|
||||
check_union([1, 2, 3], [2], [1, 2, 3]);
|
||||
check_union([2], [1, 2, 3], [1, 2, 3]);
|
||||
check_union([1, 3, 5, 9, 11, 16, 19, 24],
|
||||
[-2, 1, 5, 9, 13, 19],
|
||||
[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip() {
|
||||
let mut x = BTreeSet::new();
|
||||
x.insert(5u);
|
||||
x.insert(12u);
|
||||
x.insert(11u);
|
||||
|
||||
let mut y = BTreeSet::new();
|
||||
y.insert("foo");
|
||||
y.insert("bar");
|
||||
|
||||
let x = x;
|
||||
let y = y;
|
||||
let mut z = x.iter().zip(y.iter());
|
||||
|
||||
// FIXME: #5801: this needs a type hint to compile...
|
||||
let result: Option<(&uint, & &'static str)> = z.next();
|
||||
assert_eq!(result.unwrap(), (&5u, &("bar")));
|
||||
|
||||
let result: Option<(&uint, & &'static str)> = z.next();
|
||||
assert_eq!(result.unwrap(), (&11u, &("foo")));
|
||||
|
||||
let result: Option<(&uint, & &'static str)> = z.next();
|
||||
assert!(result.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_iter() {
|
||||
let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
let set: BTreeSet<int> = xs.iter().map(|&x| x).collect();
|
||||
|
||||
for x in xs.iter() {
|
||||
assert!(set.contains(x));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_show() {
|
||||
let mut set: BTreeSet<int> = BTreeSet::new();
|
||||
let empty: BTreeSet<int> = BTreeSet::new();
|
||||
|
||||
set.insert(1);
|
||||
set.insert(2);
|
||||
|
||||
let set_str = format!("{}", set);
|
||||
|
||||
assert!(set_str == "{1, 2}".to_string());
|
||||
assert_eq!(format!("{}", empty), "{}".to_string());
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ extern crate alloc;
|
||||
use core::prelude::Option;
|
||||
|
||||
pub use bitv::{Bitv, BitvSet};
|
||||
pub use btree::BTree;
|
||||
pub use btree::{BTreeMap, BTreeSet};
|
||||
pub use core::prelude::Collection;
|
||||
pub use dlist::DList;
|
||||
pub use enum_set::EnumSet;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
pub use core_collections::{Collection, Mutable, Map, MutableMap};
|
||||
pub use core_collections::{Set, MutableSet, Deque, MutableSeq};
|
||||
pub use core_collections::{Bitv, BitvSet, BTree, DList, EnumSet};
|
||||
pub use core_collections::{Bitv, BitvSet, BTreeMap, BTreeSet, DList, EnumSet};
|
||||
pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap};
|
||||
pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet};
|
||||
pub use core_collections::{bitv, btree, dlist, enum_set};
|
||||
|
Loading…
Reference in New Issue
Block a user