Skip to content

Commit d3d0b20

Browse files
Increase quickSort insertion threshold to 32 and organize implementation
Increases _pdqInsertionSortThreshold from 24 to 32. Reorganizes the internal helper functions for quickSort and quickSortBy into distinct sections ("Direct Comparison" and "Keyed Comparison") to improve readability and maintainability.
1 parent 6e2afe4 commit d3d0b20

File tree

1 file changed

+45
-54
lines changed

1 file changed

+45
-54
lines changed

pkgs/collection/lib/src/algorithms.dart

Lines changed: 45 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,6 @@ void _merge<E, K>(
486486
///
487487
/// The sorting algorithm is a Pattern-defeating Quicksort (pdqsort), a
488488
/// hybrid of Quicksort, Heapsort, and Insertion Sort.
489-
/// It is not stable, but is typically very fast.
490-
///
491-
/// This implementation is highly efficient for common data patterns
492-
/// (such as sorted, reverse-sorted, or with few unique values) and has a
493-
/// guaranteed worst-case time complexity of O(n*log(n)).
494-
///
495-
/// For a stable sort, use [mergeSort].
496489
void quickSort<E>(
497490
List<E> elements,
498491
int Function(E a, E b) compare, [
@@ -504,6 +497,36 @@ void quickSort<E>(
504497
_pdqSortImpl(elements, compare, start, end, _log2(end - start));
505498
}
506499

500+
/// Sorts a list between [start] (inclusive) and [end] (exclusive) by key.
501+
///
502+
/// Elements are ordered by the [compare] function applied to the result of
503+
/// the [keyOf] function.
504+
void quickSortBy<E, K>(
505+
List<E> elements,
506+
K Function(E element) keyOf,
507+
int Function(K a, K b) compare, [
508+
int start = 0,
509+
int? end,
510+
]) {
511+
end = RangeError.checkValidRange(start, end, elements.length);
512+
if (end - start < 2) return;
513+
_pdqSortByImpl(elements, keyOf, compare, start, end, _log2(end - start));
514+
}
515+
516+
/// Minimum list size below which pdqsort uses insertion sort.
517+
const int _pdqInsertionSortThreshold = 32;
518+
519+
/// Computes the base-2 logarithm of [n].
520+
/// Computes the base-2 logarithm of [n].
521+
///
522+
/// Uses bitLength to compute the floor(log2(n)) efficiently.
523+
/// For n == 0 we return 0.
524+
int _log2(int n) => n > 0 ? n.bitLength - 1 : 0;
525+
526+
// ==========================================
527+
// Implementation: Direct Comparison
528+
// ==========================================
529+
507530
void _pdqSortImpl<E>(List<E> elements, int Function(E, E) compare, int start,
508531
int end, int badAllowed) {
509532
while (true) {
@@ -560,18 +583,6 @@ void _pdqSortImpl<E>(List<E> elements, int Function(E, E) compare, int start,
560583
}
561584
}
562585

563-
void _reverseRange<E>(List<E> elements, int start, int end) {
564-
var left = start;
565-
var right = end - 1;
566-
while (left < right) {
567-
final temp = elements[left];
568-
elements[left] = elements[right];
569-
elements[right] = temp;
570-
left++;
571-
right--;
572-
}
573-
}
574-
575586
bool _handlePresorted<E>(
576587
List<E> elements, int Function(E, E) compare, int start, int end) {
577588
if (compare(elements[start], elements[start + 1]) > 0) {
@@ -595,6 +606,18 @@ bool _handlePresorted<E>(
595606
return false;
596607
}
597608

609+
void _reverseRange<E>(List<E> elements, int start, int end) {
610+
var left = start;
611+
var right = end - 1;
612+
while (left < right) {
613+
final temp = elements[left];
614+
elements[left] = elements[right];
615+
elements[right] = temp;
616+
left++;
617+
right--;
618+
}
619+
}
620+
598621
void _insertionSort<E>(
599622
List<E> elements, int Function(E, E) compare, int start, int end) {
600623
for (var i = start + 1; i < end; i++) {
@@ -680,42 +703,10 @@ void _sort3<E>(
680703
}
681704
}
682705

683-
/// Sorts a list between [start] (inclusive) and [end] (exclusive) by key.
684-
///
685-
/// The sorting algorithm is a Pattern-defeating Quicksort (pdqsort), a
686-
/// hybrid of Quicksort, Heapsort, and Insertion Sort.
687-
/// It is not stable, but is typically very fast.
688-
///
689-
/// This implementation is highly efficient for common data patterns
690-
/// (such as sorted, reverse-sorted, or with few unique values) and has a
691-
/// guaranteed worst-case time complexity of O(n*log(n)).
692-
///
693-
/// Elements are ordered by the [compare] function applied to the result of
694-
/// the [keyOf] function. For a stable sort, use [mergeSortBy].
695-
void quickSortBy<E, K>(
696-
List<E> elements,
697-
K Function(E element) keyOf,
698-
int Function(K a, K b) compare, [
699-
int start = 0,
700-
int? end,
701-
]) {
702-
end = RangeError.checkValidRange(start, end, elements.length);
703-
if (end - start < 2) return;
704-
_pdqSortByImpl(elements, keyOf, compare, start, end, _log2(end - start));
705-
}
706-
707-
/// Minimum list size below which pdqsort uses insertion sort.
708-
const int _pdqInsertionSortThreshold = 24;
706+
// ==========================================
707+
// Implementation: Keyed Comparison (By)
708+
// ==========================================
709709

710-
/// Computes the base-2 logarithm of [n].
711-
/// Computes the base-2 logarithm of [n].
712-
///
713-
/// Uses bitLength to compute the floor(log2(n)) efficiently. For n == 0
714-
/// we return 0.
715-
int _log2(int n) => n > 0 ? n.bitLength - 1 : 0;
716-
717-
/// The core implementation of Pattern-defeating Quicksort.
718-
///
719710
/// [badAllowed] tracks how many bad pivot selections are allowed before
720711
/// falling back to heap sort.
721712
void _pdqSortByImpl<E, K>(List<E> elements, K Function(E) keyOf,

0 commit comments

Comments
 (0)