499 字
2 分钟

快速排序

2025-05-04
无标签
文章目录

定义#

三路快速排序(英语:3-way Radix Quicksort)是快速排序和 基数排序 的混合。

过程#

三路快速排序在随机选取分界点 mm 后,将待排数列划分为三个部分:小于 mm 、等于 mm 以及大于 mm 。这样做即实现了将与分界元素相等的元素聚集在分界元素周围这一效果。

实现#

递归实现

template <class T>
void quick_sort(T arr[], const int len)
{
if (len <= 1)
return;
const T pivot = arr[rand() % len];
// i:当前下标
// arr[0, j],存储小于 pivot 的元素
// arr[k, len - 1],储大于 pivot 的元素
int i = 0, j = 0, k = len;
// 完成一趟三路快排,将序列分为:
// 小于 pivot 的元素 | 等于 pivot 的元素 | 大于 pivot 的元素
while (i < k)
{
if (arr[i] < pivot)
swap(arr[i++], arr[j++]);
else if (arr[i] > pivot)
swap(arr[i], arr[k--])
else
i++;
}
// 递归完成对于两个子序列的快速排序
quick_sort(arr, j);
quick_sort(arr + k, len - k);
}

非递归实现

template <class T>
void quick_sort_non_recursive(T arr[], const int len) {
if (len <= 1)
return;
// 使用栈来存储待排序的子数组的起始和结束位置
stack<pair<int, int>> stk;
stk.push({0, len - 1});
while (!stk.empty()) {
auto [left, right] = stk.top();
stk.pop();
if (left >= right) continue;
// 选择基准值
const T pivot = arr[left + rand() % (right - left + 1)];
int i = left, j = left, k = right;
// 三路划分
while (i <= k) {
if (arr[i] < pivot) {
swap(arr[i++], arr[j++]);
} else if (arr[i] > pivot) {
swap(arr[i], arr[k--]);
} else {
i++;
}
}
// 将子数组的边界压入栈中
stk.push({left, j - 1});
stk.push({k + 1, right});
}
}

性质#

稳定性#

快速排序是一种不稳定的排序算法。

时间复杂度#

快速排序的最优时间复杂度和平均时间复杂度为 O(nlogn)O(n\log n),最坏时间复杂度为 n2n^2
对于最优情况,每一次选择的分界值都是序列的中位数。
对于最坏情况,每一次选择的分界值都是序列的最值。

Reference#

快速排序 - OI Wiki