Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 273c6c3

Browse files
committedJan 17, 2023
Add heapsort fallback in select_nth_unstable
1 parent 38a76f3 commit 273c6c3

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed
 

‎library/core/src/slice/sort.rs

+22
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,15 @@ fn partition_at_index_loop<'a, T, F>(
831831
) where
832832
F: FnMut(&T, &T) -> bool,
833833
{
834+
// Limit the amount of iterations and fall back to heapsort, similarly to `slice::sort_unstable`.
835+
// This lowers the worst case running time from O(n^2) to O(n log n).
836+
// FIXME: Investigate whether it would be better to use something like Median of Medians
837+
// or Fast Deterministic Selection to guarantee O(n) worst case.
838+
let mut limit = usize::BITS - v.len().leading_zeros();
839+
840+
// True if the last partitioning was reasonably balanced.
841+
let mut was_balanced = true;
842+
834843
loop {
835844
// For slices of up to this length it's probably faster to simply sort them.
836845
const MAX_INSERTION: usize = 10;
@@ -839,6 +848,18 @@ fn partition_at_index_loop<'a, T, F>(
839848
return;
840849
}
841850

851+
if limit == 0 {
852+
heapsort(v, is_less);
853+
return;
854+
}
855+
856+
// If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
857+
// some elements around. Hopefully we'll choose a better pivot this time.
858+
if !was_balanced {
859+
break_patterns(v);
860+
limit -= 1;
861+
}
862+
842863
// Choose a pivot
843864
let (pivot, _) = choose_pivot(v, is_less);
844865

@@ -863,6 +884,7 @@ fn partition_at_index_loop<'a, T, F>(
863884
}
864885

865886
let (mid, _) = partition(v, pivot, is_less);
887+
was_balanced = cmp::min(mid, v.len() - mid) >= v.len() / 8;
866888

867889
// Split the slice into `left`, `pivot`, and `right`.
868890
let (left, right) = v.split_at_mut(mid);

0 commit comments

Comments
 (0)
Please sign in to comment.