@@ -48,21 +48,21 @@ where
48
48
S : DataMut ,
49
49
S2 : Data < Elem = usize > ;
50
50
51
- /// Partitions the array in increasing order based on the values initially located at `0` and
52
- /// `n - 1` where `n` is the number of elements in the array and returns the new indexes of the
53
- /// values.
51
+ /// Partitions the array in increasing order at two skewed pivot values as 1st and 3rd element
52
+ /// of a sorted sample of 5 equally spaced elements around the center and returns their indexes.
53
+ /// For arrays of less than 42 elements the outermost elements serve as sample for pivot values.
54
54
///
55
- /// The elements are rearranged in such a way that the values initially located at `0` and
56
- /// `n - 1` are moved to the position it would be in an array sorted in increasing order. The
57
- /// return values are the new indexes of the values after rearrangement. All elements less than
58
- /// the values are moved to their left and all elements equal or greater than the values are
59
- /// moved to their right. The ordering of the elements in the three partitions is undefined.
55
+ /// The elements are rearranged in such a way that the two pivot values are moved to the indexes
56
+ /// they would be in an array sorted in increasing order. The return values are the new indexes
57
+ /// of the values after rearrangement. All elements less than the values are moved to their left
58
+ /// and all elements equal or greater than the values are moved to their right. The ordering of
59
+ /// the elements in the three partitions is undefined.
60
60
///
61
61
/// The array is shuffled **in place**, no copy of the array is allocated.
62
62
///
63
- /// This method implements the partitioning scheme of [Yaroslavskiy-Bentley-Bloch Quicksort] .
63
+ /// This method performs [dual-pivot partitioning] with skewed pivot sampling .
64
64
///
65
- /// [Yaroslavskiy-Bentley-Bloch Quicksort ]: https://api.semanticscholar.org/CorpusID:51871084
65
+ /// [dual-pivot partitioning ]: https://www.wild-inter.net/publications/wild-2018b.pdf
66
66
///
67
67
/// # Example
68
68
///
@@ -151,11 +151,33 @@ where
151
151
A : Ord + Clone ,
152
152
S : DataMut ,
153
153
{
154
- // Sort `lowermost` and `uppermost` elements and use them as dual pivot.
155
154
let lowermost = 0 ;
156
155
let uppermost = self . len ( ) - 1 ;
157
- if self [ lowermost] > self [ uppermost] {
158
- self . swap ( lowermost, uppermost) ;
156
+ if self . len ( ) < 42 {
157
+ // Sort outermost elements and use them as pivots.
158
+ if self [ lowermost] > self [ uppermost] {
159
+ self . swap ( lowermost, uppermost) ;
160
+ }
161
+ } else {
162
+ // Sample indexes of 5 evenly spaced elements around the center element.
163
+ let mut samples = [ 0 ; 5 ] ;
164
+ // Assume array of at least 7 elements.
165
+ let seventh = self . len ( ) / ( samples. len ( ) + 2 ) ;
166
+ samples[ 2 ] = self . len ( ) / 2 ;
167
+ samples[ 1 ] = samples[ 2 ] - seventh;
168
+ samples[ 0 ] = samples[ 1 ] - seventh;
169
+ samples[ 3 ] = samples[ 2 ] + seventh;
170
+ samples[ 4 ] = samples[ 3 ] + seventh;
171
+ // Use insertion sort for sample elements by looking up their indexes.
172
+ for mut index in 1 ..samples. len ( ) {
173
+ while index > 0 && self [ samples[ index - 1 ] ] > self [ samples[ index] ] {
174
+ self . swap ( samples[ index - 1 ] , samples[ index] ) ;
175
+ index -= 1 ;
176
+ }
177
+ }
178
+ // Use 1st and 3rd element of sorted sample as skewed pivots.
179
+ self . swap ( lowermost, samples[ 0 ] ) ;
180
+ self . swap ( uppermost, samples[ 2 ] ) ;
159
181
}
160
182
// Increasing running and partition index starting after lower pivot.
161
183
let mut index = lowermost + 1 ;
0 commit comments