@@ -359,6 +359,74 @@ impl<T: Ord, A: Allocator> DerefMut for PeekMut<'_, T, A> {
359
359
}
360
360
361
361
impl < ' a , T : Ord , A : Allocator > PeekMut < ' a , T , A > {
362
+ /// Sifts the current element to its new position.
363
+ ///
364
+ /// Afterwards refers to the new element. Returns if the element changed.
365
+ ///
366
+ /// ## Examples
367
+ ///
368
+ /// The condition can be used to upper bound all elements in the heap. When only few elements
369
+ /// are affected, the heap's sort ensures this is faster than a reconstruction from the raw
370
+ /// element list and requires no additional allocation.
371
+ ///
372
+ /// ```
373
+ /// #![feature(binary_heap_peek_mut_refresh)]
374
+ /// use std::collections::BinaryHeap;
375
+ ///
376
+ /// let mut heap: BinaryHeap<u32> = (0..128).collect();
377
+ /// let mut peek = heap.peek_mut().unwrap();
378
+ ///
379
+ /// loop {
380
+ /// *peek = 99;
381
+ ///
382
+ /// if !peek.refresh() {
383
+ /// break;
384
+ /// }
385
+ /// }
386
+ ///
387
+ /// // Post condition, this is now an upper bound.
388
+ /// assert!(*peek < 100);
389
+ /// ```
390
+ ///
391
+ /// When the element remains the maximum after modification, the peek remains unchanged:
392
+ ///
393
+ /// ```
394
+ /// #![feature(binary_heap_peek_mut_refresh)]
395
+ /// use std::collections::BinaryHeap;
396
+ ///
397
+ /// let mut heap: BinaryHeap<u32> = [1, 2, 3].into();
398
+ /// let mut peek = heap.peek_mut().unwrap();
399
+ ///
400
+ /// assert_eq!(*peek, 3);
401
+ /// *peek = 42;
402
+ ///
403
+ /// // When we refresh, the peek is updated to the new maximum.
404
+ /// assert!(!peek.refresh(), "42 is even larger than 3");
405
+ /// assert_eq!(*peek, 42);
406
+ /// ```
407
+ #[ unstable( feature = "binary_heap_peek_mut_refresh" , issue = "138355" ) ]
408
+ #[ must_use = "is equivalent to dropping and getting a new PeekMut except for return information" ]
409
+ pub fn refresh ( & mut self ) -> bool {
410
+ // The length of the underlying heap is unchanged by sifting down. The value stored for leak
411
+ // amplification thus remains accurate. We erase the leak amplification firstly because the
412
+ // operation is then equivalent to constructing a new PeekMut and secondly this avoids any
413
+ // future complication where original_len being non-empty would be interpreted as the heap
414
+ // having been leak amplified instead of checking the heap itself.
415
+ if let Some ( original_len) = self . original_len . take ( ) {
416
+ // SAFETY: This is how many elements were in the Vec at the time of
417
+ // the BinaryHeap::peek_mut call.
418
+ unsafe { self . heap . data . set_len ( original_len. get ( ) ) } ;
419
+
420
+ // The length of the heap did not change by sifting, upholding our own invariants.
421
+
422
+ // SAFETY: PeekMut is only instantiated for non-empty heaps.
423
+ ( unsafe { self . heap . sift_down ( 0 ) } ) != 0
424
+ } else {
425
+ // The element was not modified.
426
+ false
427
+ }
428
+ }
429
+
362
430
/// Removes the peeked value from the heap and returns it.
363
431
#[ stable( feature = "binary_heap_peek_mut_pop" , since = "1.18.0" ) ]
364
432
pub fn pop ( mut this : PeekMut < ' a , T , A > ) -> T {
@@ -670,6 +738,8 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
670
738
/// # Safety
671
739
///
672
740
/// The caller must guarantee that `pos < self.len()`.
741
+ ///
742
+ /// Returns the new position of the element.
673
743
unsafe fn sift_up ( & mut self , start : usize , pos : usize ) -> usize {
674
744
// Take out the value at `pos` and create a hole.
675
745
// SAFETY: The caller guarantees that pos < self.len()
@@ -696,10 +766,12 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
696
766
/// Take an element at `pos` and move it down the heap,
697
767
/// while its children are larger.
698
768
///
769
+ /// Returns the new position of the element.
770
+ ///
699
771
/// # Safety
700
772
///
701
773
/// The caller must guarantee that `pos < end <= self.len()`.
702
- unsafe fn sift_down_range ( & mut self , pos : usize , end : usize ) {
774
+ unsafe fn sift_down_range ( & mut self , pos : usize , end : usize ) -> usize {
703
775
// SAFETY: The caller guarantees that pos < end <= self.len().
704
776
let mut hole = unsafe { Hole :: new ( & mut self . data , pos) } ;
705
777
let mut child = 2 * hole. pos ( ) + 1 ;
@@ -719,7 +791,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
719
791
// SAFETY: child is now either the old child or the old child+1
720
792
// We already proven that both are < self.len() and != hole.pos()
721
793
if hole. element ( ) >= unsafe { hole. get ( child) } {
722
- return ;
794
+ return hole . pos ( ) ;
723
795
}
724
796
725
797
// SAFETY: same as above.
@@ -734,16 +806,18 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
734
806
// child == 2 * hole.pos() + 1 != hole.pos().
735
807
unsafe { hole. move_to ( child) } ;
736
808
}
809
+
810
+ hole. pos ( )
737
811
}
738
812
739
813
/// # Safety
740
814
///
741
815
/// The caller must guarantee that `pos < self.len()`.
742
- unsafe fn sift_down ( & mut self , pos : usize ) {
816
+ unsafe fn sift_down ( & mut self , pos : usize ) -> usize {
743
817
let len = self . len ( ) ;
744
818
// SAFETY: pos < len is guaranteed by the caller and
745
819
// obviously len = self.len() <= self.len().
746
- unsafe { self . sift_down_range ( pos, len) } ;
820
+ unsafe { self . sift_down_range ( pos, len) }
747
821
}
748
822
749
823
/// Take an element at `pos` and move it all the way down the heap,
0 commit comments