|
153 | 153 |
|
154 | 154 | use core::iter::FromIterator;
|
155 | 155 | use core::mem::swap;
|
| 156 | +use core::mem::size_of; |
156 | 157 | use core::ptr;
|
157 | 158 | use core::fmt;
|
158 | 159 |
|
159 | 160 | use slice;
|
160 | 161 | use vec::{self, Vec};
|
161 | 162 |
|
| 163 | +use super::SpecExtend; |
| 164 | + |
162 | 165 | /// A priority queue implemented with a binary heap.
|
163 | 166 | ///
|
164 | 167 | /// This will be a max-heap.
|
@@ -738,6 +741,71 @@ impl<T: Ord> BinaryHeap<T> {
|
738 | 741 | pub fn clear(&mut self) {
|
739 | 742 | self.drain();
|
740 | 743 | }
|
| 744 | + |
| 745 | + fn rebuild(&mut self) { |
| 746 | + let mut n = self.len() / 2; |
| 747 | + while n > 0 { |
| 748 | + n -= 1; |
| 749 | + self.sift_down(n); |
| 750 | + } |
| 751 | + } |
| 752 | + |
| 753 | + /// Moves all the elements of `other` into `self`, leaving `other` empty. |
| 754 | + /// |
| 755 | + /// # Examples |
| 756 | + /// |
| 757 | + /// Basic usage: |
| 758 | + /// |
| 759 | + /// ``` |
| 760 | + /// #![feature(binary_heap_append)] |
| 761 | + /// |
| 762 | + /// use std::collections::BinaryHeap; |
| 763 | + /// |
| 764 | + /// let v = vec![-10, 1, 2, 3, 3]; |
| 765 | + /// let mut a = BinaryHeap::from(v); |
| 766 | + /// |
| 767 | + /// let v = vec![-20, 5, 43]; |
| 768 | + /// let mut b = BinaryHeap::from(v); |
| 769 | + /// |
| 770 | + /// a.append(&mut b); |
| 771 | + /// |
| 772 | + /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); |
| 773 | + /// assert!(b.is_empty()); |
| 774 | + /// ``` |
| 775 | + #[unstable(feature = "binary_heap_append", |
| 776 | + reason = "needs to be audited", |
| 777 | + issue = "32526")] |
| 778 | + pub fn append(&mut self, other: &mut Self) { |
| 779 | + if self.len() < other.len() { |
| 780 | + swap(self, other); |
| 781 | + } |
| 782 | + |
| 783 | + if other.is_empty() { |
| 784 | + return; |
| 785 | + } |
| 786 | + |
| 787 | + #[inline(always)] |
| 788 | + fn log2_fast(x: usize) -> usize { |
| 789 | + 8 * size_of::<usize>() - (x.leading_zeros() as usize) - 1 |
| 790 | + } |
| 791 | + |
| 792 | + // `rebuild` takes O(len1 + len2) operations |
| 793 | + // and about 2 * (len1 + len2) comparisons in the worst case |
| 794 | + // while `extend` takes O(len2 * log_2(len1)) operations |
| 795 | + // and about 1 * len2 * log_2(len1) comparisons in the worst case, |
| 796 | + // assuming len1 >= len2. |
| 797 | + #[inline] |
| 798 | + fn better_to_rebuild(len1: usize, len2: usize) -> bool { |
| 799 | + 2 * (len1 + len2) < len2 * log2_fast(len1) |
| 800 | + } |
| 801 | + |
| 802 | + if better_to_rebuild(self.len(), other.len()) { |
| 803 | + self.data.append(&mut other.data); |
| 804 | + self.rebuild(); |
| 805 | + } else { |
| 806 | + self.extend(other.drain()); |
| 807 | + } |
| 808 | + } |
741 | 809 | }
|
742 | 810 |
|
743 | 811 | /// Hole represents a hole in a slice i.e. an index without valid value
|
@@ -917,11 +985,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
|
917 | 985 | impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
|
918 | 986 | fn from(vec: Vec<T>) -> BinaryHeap<T> {
|
919 | 987 | let mut heap = BinaryHeap { data: vec };
|
920 |
| - let mut n = heap.len() / 2; |
921 |
| - while n > 0 { |
922 |
| - n -= 1; |
923 |
| - heap.sift_down(n); |
924 |
| - } |
| 988 | + heap.rebuild(); |
925 | 989 | heap
|
926 | 990 | }
|
927 | 991 | }
|
@@ -980,7 +1044,26 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
|
980 | 1044 |
|
981 | 1045 | #[stable(feature = "rust1", since = "1.0.0")]
|
982 | 1046 | impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
| 1047 | + #[inline] |
983 | 1048 | fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
| 1049 | + <Self as SpecExtend<I>>::spec_extend(self, iter); |
| 1050 | + } |
| 1051 | +} |
| 1052 | + |
| 1053 | +impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> { |
| 1054 | + default fn spec_extend(&mut self, iter: I) { |
| 1055 | + self.extend_desugared(iter.into_iter()); |
| 1056 | + } |
| 1057 | +} |
| 1058 | + |
| 1059 | +impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> { |
| 1060 | + fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) { |
| 1061 | + self.append(other); |
| 1062 | + } |
| 1063 | +} |
| 1064 | + |
| 1065 | +impl<T: Ord> BinaryHeap<T> { |
| 1066 | + fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) { |
984 | 1067 | let iterator = iter.into_iter();
|
985 | 1068 | let (lower, _) = iterator.size_hint();
|
986 | 1069 |
|
|
0 commit comments