diff --git a/AK/QuickSort.h b/AK/QuickSort.h index cef2a001fee..27964915220 100644 --- a/AK/QuickSort.h +++ b/AK/QuickSort.h @@ -18,62 +18,75 @@ namespace AK { template void dual_pivot_quick_sort(Collection& col, int start, int end, LessThan less_than) { - int size = end - start + 1; - if (size <= 1) { - return; - } - - if (size > 3) { - int third = size / 3; - if (less_than(col[start + third], col[end - third])) { - swap(col[start + third], col[start]); - swap(col[end - third], col[end]); - } else { - swap(col[start + third], col[end]); - swap(col[end - third], col[start]); - } - } else { - if (!less_than(col[start], col[end])) { - swap(col[start], col[end]); - } - } - - int j = start + 1; - int k = start + 1; - int g = end - 1; - - auto&& left_pivot = col[start]; - auto&& right_pivot = col[end]; - - while (k <= g) { - if (less_than(col[k], left_pivot)) { - swap(col[k], col[j]); - j++; - } else if (!less_than(col[k], right_pivot)) { - while (!less_than(col[g], right_pivot) && k < g) { - g--; + while (start < end) { + int size = end - start + 1; + if (size > 3) { + int third = size / 3; + if (less_than(col[start + third], col[end - third])) { + swap(col[start + third], col[start]); + swap(col[end - third], col[end]); + } else { + swap(col[start + third], col[end]); + swap(col[end - third], col[start]); } - swap(col[k], col[g]); - g--; + } else { + if (!less_than(col[start], col[end])) { + swap(col[start], col[end]); + } + } + + int j = start + 1; + int k = start + 1; + int g = end - 1; + + auto&& left_pivot = col[start]; + auto&& right_pivot = col[end]; + + while (k <= g) { if (less_than(col[k], left_pivot)) { swap(col[k], col[j]); j++; + } else if (!less_than(col[k], right_pivot)) { + while (!less_than(col[g], right_pivot) && k < g) { + g--; + } + swap(col[k], col[g]); + g--; + if (less_than(col[k], left_pivot)) { + swap(col[k], col[j]); + j++; + } } + k++; + } + j--; + g++; + + swap(col[start], col[j]); + swap(col[end], col[g]); + + int left_pointer = j; + int right_pointer = g; + + int left_size = left_pointer - start; + int middle_size = right_pointer - (left_pointer + 1); + int right_size = (end + 1) - (right_pointer + 1); + + if (left_size >= middle_size && left_size >= right_size) { + dual_pivot_quick_sort(col, left_pointer + 1, right_pointer - 1, less_than); + dual_pivot_quick_sort(col, right_pointer + 1, end, less_than); + end = left_pointer - 1; + } else if (middle_size >= right_size) { + dual_pivot_quick_sort(col, start, left_pointer - 1, less_than); + dual_pivot_quick_sort(col, right_pointer + 1, end, less_than); + start = left_pointer + 1; + end = right_pointer - 1; + } else { + dual_pivot_quick_sort(col, start, left_pointer - 1, less_than); + dual_pivot_quick_sort(col, left_pointer + 1, right_pointer - 1, less_than); + start = right_pointer + 1; } - k++; } - j--; - g++; - - swap(col[start], col[j]); - swap(col[end], col[g]); - - int left_pointer = j; - int right_pointer = g; - - dual_pivot_quick_sort(col, start, left_pointer - 1, less_than); - dual_pivot_quick_sort(col, left_pointer + 1, right_pointer - 1, less_than); - dual_pivot_quick_sort(col, right_pointer + 1, end, less_than); } template