From 75f6454de728e0ff8e0f558a36bab28bb4aaf9cf Mon Sep 17 00:00:00 2001 From: wilsonk Date: Sat, 18 Apr 2020 04:58:49 -0700 Subject: [PATCH] AK: Dual pivot quicksort implementation (#1838) --- AK/QuickSort.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/AK/QuickSort.h b/AK/QuickSort.h index a52fb39cdb..fb5868c9e3 100644 --- a/AK/QuickSort.h +++ b/AK/QuickSort.h @@ -30,6 +30,61 @@ namespace AK { +/* This is a dual pivot quick sort. It is quite a bit faster than the single + * pivot quick_sort below. The other quick_sort below should only be used when + * you are stuck with simple iterators to a container and you don't have access + * to the container itself. + */ +template +void dual_pivot_quick_sort(Collection& col, int start, int end, LessThan less_than) +{ + if (start >= end) { + return; + } + + int left_pointer, right_pointer; + 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]); + + left_pointer = j; + 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 void quick_sort(Iterator start, Iterator end, LessThan less_than) { @@ -65,13 +120,14 @@ void quick_sort(Iterator start, Iterator end) template void quick_sort(Collection& collection, LessThan less_than) { - quick_sort(collection.begin(), collection.end(), move(less_than)); + dual_pivot_quick_sort(collection, 0, collection.size() - 1, move(less_than)); } template void quick_sort(Collection& collection) { - quick_sort(collection.begin(), collection.end()); + dual_pivot_quick_sort(collection, 0, collection.size() - 1, + [](auto& a, auto& b) { return a < b; }); } }