mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:07:45 +00:00
AK: Guarantee a maximum stack depth for dual_pivot_quick_sort
When the two chosen pivots happen to be the smallest and largest elements of the array, three partitions will be created, two of size 0 and one of size n-2. If this happens on each recursive call to dual_pivot_quick_sort, the stack depth will reach approximately n/2. To avoid the stack from deepening, iteration can be used for the largest of the three partitions. This ensures the stack depth will only increase for partitions of size n/2 or smaller, which results in a maximum stack depth of log(n).
This commit is contained in:
parent
67b0d04315
commit
c9f3cc6dcc
1 changed files with 62 additions and 49 deletions
111
AK/QuickSort.h
111
AK/QuickSort.h
|
@ -18,62 +18,75 @@ namespace AK {
|
||||||
template<typename Collection, typename LessThan>
|
template<typename Collection, typename LessThan>
|
||||||
void dual_pivot_quick_sort(Collection& col, int start, int end, LessThan less_than)
|
void dual_pivot_quick_sort(Collection& col, int start, int end, LessThan less_than)
|
||||||
{
|
{
|
||||||
int size = end - start + 1;
|
while (start < end) {
|
||||||
if (size <= 1) {
|
int size = end - start + 1;
|
||||||
return;
|
if (size > 3) {
|
||||||
}
|
int third = size / 3;
|
||||||
|
if (less_than(col[start + third], col[end - third])) {
|
||||||
if (size > 3) {
|
swap(col[start + third], col[start]);
|
||||||
int third = size / 3;
|
swap(col[end - third], col[end]);
|
||||||
if (less_than(col[start + third], col[end - third])) {
|
} else {
|
||||||
swap(col[start + third], col[start]);
|
swap(col[start + third], col[end]);
|
||||||
swap(col[end - third], col[end]);
|
swap(col[end - third], col[start]);
|
||||||
} 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--;
|
|
||||||
}
|
}
|
||||||
swap(col[k], col[g]);
|
} else {
|
||||||
g--;
|
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)) {
|
if (less_than(col[k], left_pivot)) {
|
||||||
swap(col[k], col[j]);
|
swap(col[k], col[j]);
|
||||||
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<typename Iterator, typename LessThan>
|
template<typename Iterator, typename LessThan>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue