快排
最基本的快排:
int partition(int arr[], int l, int r)
{
int k = l;
int pivot = arr[r];
for (int i = l; i != r; ++i){
if (arr[i] < pivot){
std::swap(arr[i], arr[k++]);
}
}
std::swap(arr[r], arr[k]);
return k;
}
void quickSort(int arr[], int l, int r)
{
if (l < r){
int pivot = partition (arr, l, r);
quickSort (arr, l, (pivot - 1));
quickSort (arr, (pivot + 1), r);
}
}
但是如果重复的元素过多,那么性能就会直线下降。所以有了如下方法:
std::pair<int, int> partition(int arr[], int l, int r)
{
int low_bound = l;
int pivots_bound = r;
const int pivot = arr[r];
for (int i = l; i != pivots_bound;){
if (arr[i] < pivot){
std::swap(arr[i++], arr[low_bound++]);
}else{
if (arr[i] == pivot){
std::swap(arr[i], arr[--pivots_bound]);
}else{
++i;
}
}
}
int offset = std::min(pivots_bound - low_bound,
r - pivots_bound + 1);
for (int i = 0; i != offset; ++i){
std::swap(arr[low_bound + i], arr[r - i]);
}
// (pivots_bound - low_bound) 的值是大于 pivot 的值的个数
return {low_bound, r - pivots_bound + low_bound};
}
void quickSort(int arr[], int l, int r)
{
if (l < r){
auto pivots_bound = partition (arr, l, r);
quickSort (arr, l, (pivots_bound.first - 1));
quickSort (arr, (pivots_bound.second + 1), r);
}
}