快速排序(QuickSort)
快速排序
#include <iostream>
#include <algorithm>
using namespace std;
//快速排序
void QuickSort1(int* arr, int low, int high) {
if (low < high) {
int pivot = arr[low];
int start = low, end = high;
while (low < high) {
while (low < high && pivot <= arr[high])
high--;
arr[low] = arr[high];
while (low < high && pivot >= arr[low])
low++;
arr[high] = arr[low];
}
arr[low] = pivot;
int pivotpos = low;
QuickSort1(arr, start, pivotpos - 1);
QuickSort1(arr, pivotpos + 1, end);
}
}
void QuickSort2(int* arr, int low, int high) {
if (low >= high) return;
int front = low, rear = high;
int pivot = arr[low];
while (low < high) {
while (low < high && arr[high] >= pivot)
high--;
while (low < high && arr[low] <= pivot)
low++;
if (low < high)
swap(arr[low], arr[high]);
}
swap(arr[front], arr[low]);
QuickSort2(arr, front, low - 1);
QuickSort2(arr, low + 1, rear);
}
//(***最优***)
void QuickSort3(int arr[], int low, int high) {
if (low >= high) return;
int i = low - 1, j = high + 1; // 从界外开始
int x = arr[(low + high) >> 1]; // 基准值为中间位置的数值
while (i < j) {
do i++; while (arr[i] < x); // i哨兵向右走,找到第一个大于等于基准值的数
do j--; while (arr[j] > x); // j哨兵向左走,找到第一个小于等于基准值的数
if (i < j) swap(arr[i], arr[j]); // 如果还没有碰面,就对调一下
}
// 递归排序左半部分和右半部分
QuickSort3(arr, low, j);
QuickSort3(arr, j + 1, high);
}
int main() {
int n;
cin >> n; // 输入数组大小
int* arr = new int[n]; // 创建数组
for (int i = 0; i < n; i++) {
cin >> arr[i]; // 输入数组元素
}
//QuickSort1(arr, 0, n - 1);
//QuickSort2(arr, 0, n - 1);
QuickSort3(arr, 0, n - 1);
// 输出排序后的数组
for (int i = 0; i < n; i++) {
cout << arr[i];
if (i < n - 1) cout << " "; // 除了最后一个元素外,后面有空格
}
return 0;
}
上述代码实现了三种不同的快速排序算法(QuickSort1、QuickSort2 和 QuickSort3),并且通过 main 函数对它们进行了测试。以下是对每种实现的详细分析以及改进建议:
QuickSort1 分析
实现特点:
- 选择
arr[low]作为基准(pivot)。 - 使用双指针(
low和high)进行分区。 - 分区过程中直接覆盖元素,最后将基准值放回正确位置。
改进建议:
- 基准选择:选择
arr[low]作为基准可能导致最坏情况(例如数组已经有序时)。可以通过随机选择基准来优化。 - 代码可读性:添加注释,解释分区逻辑。
改进后的代码:
void QuickSort1(int* arr, int low, int high) {
if (low < high) {
// 随机选择基准元素
int randomIndex = low + rand() % (high - low + 1);
swap(arr[low], arr[randomIndex]);
int pivot = arr[low];
int start = low, end = high;
while (low < high) {
while (low < high && pivot <= arr[high])
high--;
arr[low] = arr[high];
while (low < high && pivot >= arr[low])
low++;
arr[high] = arr[low];
}
arr[low] = pivot;
int pivotpos = low;
// 递归排序左半部分和右半部分
QuickSort1(arr, start, pivotpos - 1);
QuickSort1(arr, pivotpos + 1, end);
}
}
QuickSort2 分析
实现特点:
- 选择
arr[low]作为基准。 - 使用双指针(
low和high)进行分区。 - 在分区过程中,通过
swap交换元素,而不是直接覆盖。
改进建议:
- 基准选择:同样可以通过随机选择基准来优化。
- 代码可读性:添加注释,解释分区逻辑。
改进后的代码:
void QuickSort2(int* arr, int low, int high) {
if (low >= high) return;
// 随机选择基准元素
int randomIndex = low + rand() % (high - low + 1);
swap(arr[low], arr[randomIndex]);
int pivot = arr[low];
int front = low, rear = high;
while (low < high) {
while (low < high && arr[high] >= pivot)
high--;
while (low < high && arr[low] <= pivot)
low++;
if (low < high)
swap(arr[low], arr[high]);
}
swap(arr[front], arr[low]);
// 递归排序左半部分和右半部分
QuickSort2(arr, front, low - 1);
QuickSort2(arr, low + 1, rear);
}
QuickSort3 分析
实现特点:
- 选择中间元素
arr[(low + high) >> 1]作为基准。 - 使用双指针(
i和j)从数组两端向中间扫描。 - 通过
swap交换元素,直到指针相遇。
优点:
- 基准选择较为合理,避免了最坏情况。
- 代码逻辑清晰,易于理解。
改进建议:
- 代码可读性:添加注释,解释指针移动和交换的逻辑。
改进后的代码:
void QuickSort3(int arr[], int low, int high) {
if (low >= high) return;
int i = low - 1, j = high + 1; // 从界外开始
int x = arr[(low + high) >> 1]; // 基准值为中间位置的数值
while (i < j) {
do i++; while (arr[i] < x); // i哨兵向右走,找到第一个大于等于基准值的数
do j--; while (arr[j] > x); // j哨兵向左走,找到第一个小于等于基准值的数
if (i < j) swap(arr[i], arr[j]); // 如果还没有碰面,就对调一下
}
// 递归排序左半部分和右半部分
QuickSort3(arr, low, j);
QuickSort3(arr, j + 1, high);
}
main 函数分析
实现特点:
- 测试了三种快速排序算法。
- 输出排序前后的数组。
改进建议:
- 释放动态分配的内存:如果使用动态数组,记得释放内存。
- 代码可读性:添加注释,解释测试逻辑。
改进后的代码:
int main() {
int arr[9] = {6, 4, 7, 9, 1, 6, 2, 98, 1};
int len = sizeof(arr) / sizeof(int);
cout << "排序前的: ";
for (int i = 0; i < len; ++i) {
cout << arr[i] << " ";
}
cout << endl;
cout << "长度:" << len << endl;
// 选择一种快速排序算法进行测试
// QuickSort1(arr, 0, len - 1);
// QuickSort2(arr, 0, len - 1);
QuickSort3(arr, 0, len - 1);
cout << "排序后的: ";
for (int i = 0; i < len; ++i) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
总结
QuickSort1和QuickSort2:可以通过随机选择基准来优化性能。QuickSort3:实现较为合理,基准选择避免了最坏情况。- 代码风格:添加注释,提高代码可读性。
- 测试:通过
main函数测试了三种算法的正确性。

浙公网安备 33010602011771号