快速排序

题目描述
快速排序是一种高效的排序算法,它采用了分治(Divide and Conquer)的思想。基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

输入格式
输入共 2 行,第一行是一个整数 n,表示数组的长度。第二行包含 n 个整数,表示待排序的数组。

输出格式
输出共 1 行,包含 n 个整数,表示排序后的数组(升序排列)。

数据范围
1 ≤ n ≤ 10000
-10000 ≤ 数组元素 ≤ 10000

输入样例:

1
2
8
3 1 4 1 5 9 2 6

输出样例:

1
1 1 2 3 4 5 6 9

注意事项

  • 快速排序的平均时间复杂度为 O(nlogn),最坏时间复杂度为 O(n²),空间复杂度为 O(logn)。
  • 快速排序是不稳定的排序算法。
  • 在大多数情况下,快速排序是实际应用中性能最好的排序算法之一。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
using namespace std;

// 交换两个元素
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}

// 分区函数,返回枢轴元素的最终位置
int partition(int a[], int low, int high)
{
int pivot = a[high]; // 选择最右边的元素作为枢轴
int i = low - 1; // i指向小于枢轴元素的最后一个位置

for (int j = low; j < high; j++)
{
if (a[j] <= pivot)
{
i++;
swap(a[i], a[j]);
}
}
swap(a[i + 1], a[high]); // 将枢轴元素放到正确的位置
return i + 1; // 返回枢轴元素的最终位置
}

// 快速排序函数
void quickSort(int a[], int low, int high)
{
if (low < high)
{
int pivot_index = partition(a, low, high); // 获取枢轴元素的最终位置
quickSort(a, low, pivot_index - 1); // 递归排序枢轴元素左边的子数组
quickSort(a, pivot_index + 1, high); // 递归排序枢轴元素右边的子数组
}
}

int main()
{
int n;
cin >> n;
int a[n];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}

quickSort(a, 0, n - 1); // 对整个数组进行快速排序

// 输出排序后的数组
for (int i = 0; i < n; i++)
{
cout << a[i] << " ";
}
cout << endl;

return 0;
}

时间复杂度

  • 平均时间复杂度:O(nlogn),其中 n 为数组的长度。
  • 最坏时间复杂度:O(n²)(当输入数组已经排序或接近排序时)。
  • 空间复杂度:O(logn)(由递归调用栈占用的空间)。

代码解释

  • 快速排序的核心是分区(partition)操作,我们选择一个元素作为枢轴(pivot),然后将数组重新排列,使得所有小于枢轴的元素都在枢轴的左边,所有大于枢轴的元素都在枢轴的右边。
  • 然后,我们递归地对枢轴左右两边的子数组应用相同的操作。
  • 在这个实现中,我们选择最右边的元素作为枢轴,使用双指针技术来完成分区操作。
  • 递归的终止条件是子数组的长度小于或等于1(即low >= high)。