Auto merge of #30426 - gereeter:btree-rewrite, r=Gankro

Despite being over 700 lines shorter, this implementation should use less memory than the previous one and is faster on at least insertions and iteration, the latter improving approximately 5x.

Technically a [breaking-change] due to removal of deprecated functions.

cc @apasel422 @Gankro @goyox86

Fixes #27865.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/rust-lang/rust/30426)
<!-- Reviewable:end -->
This commit is contained in:
bors 2016-01-17 06:47:55 +00:00
commit 88463364bf
6 changed files with 2162 additions and 2841 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
// except according to those terms.
mod node;
mod search;
pub mod map;
pub mod set;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
// Copyright 2015 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.
use core::cmp::Ordering;
use borrow::Borrow;
use super::node::{Handle, NodeRef, marker};
use super::node::ForceResult::*;
use self::SearchResult::*;
pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>)
}
pub fn search_tree<BorrowType, K, V, Q: ?Sized>(
mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
key: &Q
) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
where Q: Ord, K: Borrow<Q> {
loop {
match search_node(node, key) {
Found(handle) => return Found(handle),
GoDown(handle) => match handle.force() {
Leaf(leaf) => return GoDown(leaf),
Internal(internal) => {
node = internal.descend();
continue;
}
}
}
}
}
pub fn search_node<BorrowType, K, V, Type, Q: ?Sized>(
node: NodeRef<BorrowType, K, V, Type>,
key: &Q
) -> SearchResult<BorrowType, K, V, Type, Type>
where Q: Ord, K: Borrow<Q> {
match search_linear(&node, key) {
(idx, true) => Found(
Handle::new_kv(node, idx)
),
(idx, false) => SearchResult::GoDown(
Handle::new_edge(node, idx)
)
}
}
fn search_linear<BorrowType, K, V, Type, Q: ?Sized>(
node: &NodeRef<BorrowType, K, V, Type>,
key: &Q
) -> (usize, bool)
where Q: Ord, K: Borrow<Q> {
for (i, k) in node.keys().iter().enumerate() {
match key.cmp(k.borrow()) {
Ordering::Greater => {},
Ordering::Equal => return (i, true),
Ordering::Less => return (i, false)
}
}
(node.keys().len(), false)
}

View File

@ -43,8 +43,8 @@
#![feature(iter_arith)]
#![feature(iter_arith)]
#![feature(lang_items)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(oom)]
#![feature(pattern)]
#![feature(shared)]
#![feature(slice_bytes)]
@ -55,7 +55,7 @@
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(unsafe_no_drop_flag)]
#![cfg_attr(test, feature(clone_from_slice, rand, test))]
#![no_std]

View File

@ -346,6 +346,38 @@ fn test_bad_zst() {
}
}
#[test]
fn test_clone() {
let mut map = BTreeMap::new();
let size = 100;
assert_eq!(map.len(), 0);
for i in 0..size {
assert_eq!(map.insert(i, 10*i), None);
assert_eq!(map.len(), i + 1);
assert_eq!(map, map.clone());
}
for i in 0..size {
assert_eq!(map.insert(i, 100*i), Some(10*i));
assert_eq!(map.len(), size);
assert_eq!(map, map.clone());
}
for i in 0..size/2 {
assert_eq!(map.remove(&(i*2)), Some(i*200));
assert_eq!(map.len(), size - i - 1);
assert_eq!(map, map.clone());
}
for i in 0..size/2 {
assert_eq!(map.remove(&(2*i)), None);
assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100));
assert_eq!(map.len(), size/2 - i - 1);
assert_eq!(map, map.clone());
}
}
mod bench {
use std::collections::BTreeMap;
use std::__rand::{Rng, thread_rng};