49
49
50
50
// Rearrange the into a valid heap by reordering from the second-bottom-most layer up
51
51
// Slightly faster than ordering on each insert, but only by a factor of lg(k)
52
+ // The resulting heap has the **largest** item on top
52
53
for i in ( 0 ..=( storage. len ( ) / 2 ) ) . rev ( ) {
53
54
sift_down ( & mut storage, & mut is_less_than, i) ;
54
55
}
@@ -63,18 +64,23 @@ where
63
64
// Treating this as an push-and-pop saves having to write a sift-up implementation
64
65
// https://en.wikipedia.org/wiki/Binary_heap#Insert_then_extract
65
66
storage[ 0 ] = val;
67
+ // We retain the smallest items we've seen so far, but ordered largest first so we can drop the largest efficiently.
66
68
sift_down ( & mut storage, & mut is_less_than, 0 ) ;
67
69
}
68
70
} ) ;
69
71
}
70
72
71
- let mut heap = & mut storage[ ..] ;
73
+ // Ultimately the items need to be in least-first, strict order, but the heap is currently largest-first.
74
+ // To achieve this, repeatedly
75
+ // 1) "pop" the largest item off the heap into the tail slot of the underlying storage
76
+ // 2) shrink the logical size of the heap by 1
77
+ // 3) restore the heap property over the remaining items
72
78
79
+ let mut heap = & mut storage[ ..] ;
73
80
while heap. len ( ) > 1 {
74
81
let last_idx = heap. len ( ) - 1 ;
75
82
heap. swap ( 0 , last_idx) ;
76
- // Leaves the length shorter than the number of elements
77
- // so that sifting does not disturb already popped elements
83
+ // Sifting over a truncated slice means that the sifting will not disturb already popped elements
78
84
heap = & mut heap[ ..last_idx] ;
79
85
sift_down ( heap, & mut is_less_than, 0 ) ;
80
86
}
0 commit comments