diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index effd4ebb31672..bd329949618e5 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -354,7 +354,7 @@ impl BinaryHeap { self.data.pop().map(|mut item| { if !self.is_empty() { swap(&mut item, &mut self.data[0]); - self.sift_down(0); + self.sift_down_to_bottom(0); } item }) @@ -545,6 +545,31 @@ impl BinaryHeap { self.sift_down_range(pos, len); } + /// Take an element at `pos` and move it all the way down the heap, + /// then sift it up to its position. + /// + /// Note: This is faster when the element is known to be large / should + /// be closer to the bottom. + fn sift_down_to_bottom(&mut self, mut pos: usize) { + let end = self.len(); + let start = pos; + unsafe { + let mut hole = Hole::new(&mut self.data, pos); + let mut child = 2 * pos + 1; + while child < end { + let right = child + 1; + // compare with the greater of the two children + if right < end && !(hole.get(child) > hole.get(right)) { + child = right; + } + hole.move_to(child); + child = 2 * hole.pos() + 1; + } + pos = hole.pos; + } + self.sift_up(start, pos); + } + /// Returns the length of the binary heap. #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize {