@@ -831,6 +831,15 @@ fn partition_at_index_loop<'a, T, F>(
831
831
) where
832
832
F : FnMut ( & T , & T ) -> bool ,
833
833
{
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
+
834
843
loop {
835
844
// For slices of up to this length it's probably faster to simply sort them.
836
845
const MAX_INSERTION : usize = 10 ;
@@ -839,6 +848,18 @@ fn partition_at_index_loop<'a, T, F>(
839
848
return ;
840
849
}
841
850
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
+
842
863
// Choose a pivot
843
864
let ( pivot, _) = choose_pivot ( v, is_less) ;
844
865
@@ -863,6 +884,7 @@ fn partition_at_index_loop<'a, T, F>(
863
884
}
864
885
865
886
let ( mid, _) = partition ( v, pivot, is_less) ;
887
+ was_balanced = cmp:: min ( mid, v. len ( ) - mid) >= v. len ( ) / 8 ;
866
888
867
889
// Split the slice into `left`, `pivot`, and `right`.
868
890
let ( left, right) = v. split_at_mut ( mid) ;
0 commit comments