8
8
F : FnMut ( & I :: Item , & I :: Item ) -> Ordering ,
9
9
{
10
10
/// Sift the element currently at `origin` **away** from the root until it is properly ordered
11
- fn sift_down < T , F > ( heap : & mut [ T ] , comparator : & mut F , mut origin : usize )
11
+ fn sift_down < T , F > ( heap : & mut [ T ] , is_less_than : & mut F , mut origin : usize )
12
12
where
13
- F : FnMut ( & T , & T ) -> Ordering ,
13
+ F : FnMut ( & T , & T ) -> bool ,
14
14
{
15
15
fn children_of ( n : usize ) -> ( usize , usize ) {
16
16
( 2 * n + 1 , 2 * n + 2 )
@@ -22,15 +22,14 @@ where
22
22
return ;
23
23
}
24
24
25
- let replacement_idx = if right_idx < heap. len ( )
26
- && Ordering :: Less == comparator ( & heap[ left_idx] , & heap[ right_idx] )
27
- {
28
- right_idx
29
- } else {
30
- left_idx
31
- } ;
25
+ let replacement_idx =
26
+ if right_idx < heap. len ( ) && is_less_than ( & heap[ left_idx] , & heap[ right_idx] ) {
27
+ right_idx
28
+ } else {
29
+ left_idx
30
+ } ;
32
31
33
- if Ordering :: Less == comparator ( & heap[ origin] , & heap[ replacement_idx] ) {
32
+ if is_less_than ( & heap[ origin] , & heap[ replacement_idx] ) {
34
33
heap. swap ( origin, replacement_idx) ;
35
34
origin = replacement_idx;
36
35
} else {
@@ -44,22 +43,24 @@ where
44
43
}
45
44
let mut storage: Vec < I :: Item > = iter. by_ref ( ) . take ( k) . collect ( ) ;
46
45
46
+ let mut is_less_than = move |a : & _ , b : & _ | comparator ( a, b) == Ordering :: Less ;
47
+
47
48
// Rearrange the into a valid heap by reordering from the second-bottom-most layer up
48
49
// Slightly faster than ordering on each insert, but only by a factor of lg(k)
49
50
for i in ( 0 ..=( storage. len ( ) / 2 ) ) . rev ( ) {
50
- sift_down ( & mut storage, & mut comparator , i) ;
51
+ sift_down ( & mut storage, & mut is_less_than , i) ;
51
52
}
52
53
53
54
if k == storage. len ( ) {
54
55
// If we fill the storage, there may still be iterator elements left
55
56
// So feed them into the heap
56
57
// Also avoids unexpected behaviour with restartable iterators
57
58
iter. for_each ( |val| {
58
- if comparator ( & val, & mut storage[ 0 ] ) == Ordering :: Less {
59
+ if is_less_than ( & val, & mut storage[ 0 ] ) {
59
60
// Treating this as an push-and-pop saves having to write a sift-up implementation
60
61
// https://en.wikipedia.org/wiki/Binary_heap#Insert_then_extract
61
62
storage[ 0 ] = val;
62
- sift_down ( & mut storage, & mut comparator , 0 ) ;
63
+ sift_down ( & mut storage, & mut is_less_than , 0 ) ;
63
64
}
64
65
} ) ;
65
66
}
72
73
// Leaves the length shorter than the number of elements
73
74
// so that sifting does not disturb already popped elements
74
75
heap = & mut heap[ ..last_idx] ;
75
- sift_down ( heap, & mut comparator , 0 ) ;
76
+ sift_down ( heap, & mut is_less_than , 0 ) ;
76
77
}
77
78
78
79
storage
0 commit comments