Skip to content

Commit e752aa8

Browse files
committed
Auto merge of #33947 - xosmig:btree_split_off, r=gereeter
Implement split_off for BTreeMap and BTreeSet (RFC 509) Fixes #19986 and refactors common with append methods. It splits the tree with O(log n) operations and then calculates sizes by traversing the lower one. CC @gereeter
2 parents 728eea7 + e3adad6 commit e752aa8

File tree

7 files changed

+538
-92
lines changed

7 files changed

+538
-92
lines changed

src/libcollections/btree/map.rs

+170-2
Original file line numberDiff line numberDiff line change
@@ -842,20 +842,188 @@ impl<K: Ord, V> BTreeMap<K, V> {
842842
// Check if right-most child is underfull.
843843
let mut last_edge = internal.last_edge();
844844
let right_child_len = last_edge.reborrow().descend().len();
845-
if right_child_len < node::CAPACITY / 2 {
845+
if right_child_len < node::MIN_LEN {
846846
// We need to steal.
847847
let mut last_kv = match last_edge.left_kv() {
848848
Ok(left) => left,
849849
Err(_) => unreachable!(),
850850
};
851-
last_kv.bulk_steal_left(node::CAPACITY/2 - right_child_len);
851+
last_kv.bulk_steal_left(node::MIN_LEN - right_child_len);
852852
last_edge = last_kv.right_edge();
853853
}
854854

855855
// Go further down.
856856
cur_node = last_edge.descend();
857857
}
858858
}
859+
860+
/// Splits the collection into two at the given key. Returns everything after the given key,
861+
/// including the key.
862+
///
863+
/// # Examples
864+
///
865+
/// Basic usage:
866+
///
867+
/// ```
868+
/// #![feature(btree_split_off)]
869+
/// use std::collections::BTreeMap;
870+
///
871+
/// let mut a = BTreeMap::new();
872+
/// a.insert(1, "a");
873+
/// a.insert(2, "b");
874+
/// a.insert(3, "c");
875+
/// a.insert(17, "d");
876+
/// a.insert(41, "e");
877+
///
878+
/// let b = a.split_off(&3);
879+
///
880+
/// assert_eq!(a.len(), 2);
881+
/// assert_eq!(b.len(), 3);
882+
///
883+
/// assert_eq!(a[&1], "a");
884+
/// assert_eq!(a[&2], "b");
885+
///
886+
/// assert_eq!(b[&3], "c");
887+
/// assert_eq!(b[&17], "d");
888+
/// assert_eq!(b[&41], "e");
889+
/// ```
890+
#[unstable(feature = "btree_split_off",
891+
reason = "recently added as part of collections reform 2",
892+
issue = "19986")]
893+
pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where K: Borrow<Q> {
894+
if self.is_empty() {
895+
return Self::new();
896+
}
897+
898+
let total_num = self.len();
899+
900+
let mut right = Self::new();
901+
for _ in 0..(self.root.as_ref().height()) {
902+
right.root.push_level();
903+
}
904+
905+
{
906+
let mut left_node = self.root.as_mut();
907+
let mut right_node = right.root.as_mut();
908+
909+
loop {
910+
let mut split_edge = match search::search_node(left_node, key) {
911+
// key is going to the right tree
912+
Found(handle) => handle.left_edge(),
913+
GoDown(handle) => handle
914+
};
915+
916+
split_edge.move_suffix(&mut right_node);
917+
918+
match (split_edge.force(), right_node.force()) {
919+
(Internal(edge), Internal(node)) => {
920+
left_node = edge.descend();
921+
right_node = node.first_edge().descend();
922+
}
923+
(Leaf(_), Leaf(_)) => { break; },
924+
_ => { unreachable!(); }
925+
}
926+
}
927+
}
928+
929+
self.fix_right_border();
930+
right.fix_left_border();
931+
932+
if self.root.as_ref().height() < right.root.as_ref().height() {
933+
self.recalc_length();
934+
right.length = total_num - self.len();
935+
} else {
936+
right.recalc_length();
937+
self.length = total_num - right.len();
938+
}
939+
940+
right
941+
}
942+
943+
/// Calculates the number of elements if it is incorrect.
944+
fn recalc_length(&mut self) {
945+
fn dfs<K, V>(node: NodeRef<marker::Immut, K, V, marker::LeafOrInternal>) -> usize {
946+
let mut res = node.len();
947+
948+
if let Internal(node) = node.force() {
949+
let mut edge = node.first_edge();
950+
loop {
951+
res += dfs(edge.reborrow().descend());
952+
match edge.right_kv() {
953+
Ok(right_kv) => { edge = right_kv.right_edge(); },
954+
Err(_) => { break; }
955+
}
956+
}
957+
}
958+
959+
res
960+
}
961+
962+
self.length = dfs(self.root.as_ref());
963+
}
964+
965+
/// Removes empty levels on the top.
966+
fn fix_top(&mut self) {
967+
loop {
968+
{
969+
let node = self.root.as_ref();
970+
if node.height() == 0 || node.len() > 0 {
971+
break;
972+
}
973+
}
974+
self.root.pop_level();
975+
}
976+
}
977+
978+
fn fix_right_border(&mut self) {
979+
self.fix_top();
980+
981+
{
982+
let mut cur_node = self.root.as_mut();
983+
984+
while let Internal(node) = cur_node.force() {
985+
let mut last_kv = node.last_kv();
986+
987+
if last_kv.can_merge() {
988+
cur_node = last_kv.merge().descend();
989+
} else {
990+
let right_len = last_kv.reborrow().right_edge().descend().len();
991+
// `MINLEN + 1` to avoid readjust if merge happens on the next level.
992+
if right_len < node::MIN_LEN + 1 {
993+
last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
994+
}
995+
cur_node = last_kv.right_edge().descend();
996+
}
997+
}
998+
}
999+
1000+
self.fix_top();
1001+
}
1002+
1003+
/// The symmetric clone of `fix_right_border`.
1004+
fn fix_left_border(&mut self) {
1005+
self.fix_top();
1006+
1007+
{
1008+
let mut cur_node = self.root.as_mut();
1009+
1010+
while let Internal(node) = cur_node.force() {
1011+
let mut first_kv = node.first_kv();
1012+
1013+
if first_kv.can_merge() {
1014+
cur_node = first_kv.merge().descend();
1015+
} else {
1016+
let left_len = first_kv.reborrow().left_edge().descend().len();
1017+
if left_len < node::MIN_LEN + 1 {
1018+
first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
1019+
}
1020+
cur_node = first_kv.left_edge().descend();
1021+
}
1022+
}
1023+
}
1024+
1025+
self.fix_top();
1026+
}
8591027
}
8601028

8611029
impl<'a, K: 'a, V: 'a> IntoIterator for &'a BTreeMap<K, V> {

0 commit comments

Comments
 (0)