aboutsummaryrefslogtreecommitdiff
path: root/libcollections/binary_heap.rs
diff options
context:
space:
mode:
authorpravic <[email protected]>2016-04-29 21:16:15 +0300
committerpravic <[email protected]>2016-04-29 21:16:15 +0300
commit77e9a3167b4aaadf3583a0c1d1ee0d9e63c9a000 (patch)
tree710e445d56a1a582b8eff19b7b4b180276eae122 /libcollections/binary_heap.rs
parenttweak: /driver option specifies /fixed:no implicitly as well (diff)
downloadkmd-env-rs-77e9a3167b4aaadf3583a0c1d1ee0d9e63c9a000.tar.xz
kmd-env-rs-77e9a3167b4aaadf3583a0c1d1ee0d9e63c9a000.zip
update libcore to 2016-04-29 nightly
Diffstat (limited to 'libcollections/binary_heap.rs')
-rw-r--r--libcollections/binary_heap.rs94
1 files changed, 89 insertions, 5 deletions
diff --git a/libcollections/binary_heap.rs b/libcollections/binary_heap.rs
index c9dd1ef..43c6e6e 100644
--- a/libcollections/binary_heap.rs
+++ b/libcollections/binary_heap.rs
@@ -153,12 +153,15 @@
use core::iter::FromIterator;
use core::mem::swap;
+use core::mem::size_of;
use core::ptr;
use core::fmt;
use slice;
use vec::{self, Vec};
+use super::SpecExtend;
+
/// A priority queue implemented with a binary heap.
///
/// This will be a max-heap.
@@ -738,6 +741,71 @@ impl<T: Ord> BinaryHeap<T> {
pub fn clear(&mut self) {
self.drain();
}
+
+ fn rebuild(&mut self) {
+ let mut n = self.len() / 2;
+ while n > 0 {
+ n -= 1;
+ self.sift_down(n);
+ }
+ }
+
+ /// Moves all the elements of `other` into `self`, leaving `other` empty.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(binary_heap_append)]
+ ///
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let v = vec![-10, 1, 2, 3, 3];
+ /// let mut a = BinaryHeap::from(v);
+ ///
+ /// let v = vec![-20, 5, 43];
+ /// let mut b = BinaryHeap::from(v);
+ ///
+ /// a.append(&mut b);
+ ///
+ /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
+ /// assert!(b.is_empty());
+ /// ```
+ #[unstable(feature = "binary_heap_append",
+ reason = "needs to be audited",
+ issue = "32526")]
+ pub fn append(&mut self, other: &mut Self) {
+ if self.len() < other.len() {
+ swap(self, other);
+ }
+
+ if other.is_empty() {
+ return;
+ }
+
+ #[inline(always)]
+ fn log2_fast(x: usize) -> usize {
+ 8 * size_of::<usize>() - (x.leading_zeros() as usize) - 1
+ }
+
+ // `rebuild` takes O(len1 + len2) operations
+ // and about 2 * (len1 + len2) comparisons in the worst case
+ // while `extend` takes O(len2 * log_2(len1)) operations
+ // and about 1 * len2 * log_2(len1) comparisons in the worst case,
+ // assuming len1 >= len2.
+ #[inline]
+ fn better_to_rebuild(len1: usize, len2: usize) -> bool {
+ 2 * (len1 + len2) < len2 * log2_fast(len1)
+ }
+
+ if better_to_rebuild(self.len(), other.len()) {
+ self.data.append(&mut other.data);
+ self.rebuild();
+ } else {
+ self.extend(other.drain());
+ }
+ }
}
/// Hole represents a hole in a slice i.e. an index without valid value
@@ -851,6 +919,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
/// An iterator that moves out of a `BinaryHeap`.
#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
pub struct IntoIter<T> {
iter: vec::IntoIter<T>,
}
@@ -917,11 +986,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
fn from(vec: Vec<T>) -> BinaryHeap<T> {
let mut heap = BinaryHeap { data: vec };
- let mut n = heap.len() / 2;
- while n > 0 {
- n -= 1;
- heap.sift_down(n);
- }
+ heap.rebuild();
heap
}
}
@@ -980,7 +1045,26 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Extend<T> for BinaryHeap<T> {
+ #[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ <Self as SpecExtend<I>>::spec_extend(self, iter);
+ }
+}
+
+impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
+ default fn spec_extend(&mut self, iter: I) {
+ self.extend_desugared(iter.into_iter());
+ }
+}
+
+impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> {
+ fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) {
+ self.append(other);
+ }
+}
+
+impl<T: Ord> BinaryHeap<T> {
+ fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let iterator = iter.into_iter();
let (lower, _) = iterator.size_hint();