文章目录
- 概要
- 代码
- 输出
- 分析
- 优缺点
概要
快速排序(Quick Sort): 是一种非常高效的排序算法,基于分治法(Divide and Conquer)的思想。它的基本思想是通过一个"基准"元素(pivot)将数组分成两部分,其中一部分所有元素都比基准小,另一部分所有元素都比基准大,然后递归地对这两部分继续进行排序。
代码
#include <stdio.h>// 交换两个元素的值
void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}// 分区函数,返回分区点的索引
int partition(int arr[], int low, int high) {int pivot = arr[high]; // 选择最后一个元素作为基准int i = (low - 1); // i是较小元素的索引for (int j = low; j <= high - 1; j++) {// 如果当前元素小于或等于基准if (arr[j] <= pivot) {i++; // 增加较小元素的索引swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]); // 将基准元素放到正确的位置return (i + 1);
}// 快速排序的递归函数
void quickSort(int arr[], int low, int high) {if (low < high) {// pi是分区点索引,arr[pi]已经排好序int pi = partition(arr, low, high);// 递归排序分区点左边的子数组quickSort(arr, low, pi - 1);// 递归排序分区点右边的子数组quickSort(arr, pi + 1, high);}
}// 打印数组的函数
void printArray(int arr[], int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}// 主函数
int main() {int arr[] = {10, 7, 8, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);printf("排序前的数组: \n");printArray(arr, n);quickSort(arr, 0, n - 1);printf("排序后的数组: \n");printArray(arr, n);return 0;
}
输出
排序前的数组:
10 7 8 9 1 5
排序后的数组:
1 5 7 8 9 10
分析
针对数组【10,7,8,9,1,5】做快速排序解析,解析如下:
核心规则:选基准(第一个或者最后一个或者随机)、分区(尽量均衡)、递归。
快速排序的基本思想:
- 选择一个基准元素(pivot)。
- 将数组分为两部分:一部分比基准元素小,另一部分比基准元素大。
- 递归地对这两部分进行快速排序。
- 第一次选择基准5(最后一个元素):
分区后数组变为[1,5,8,9,10,7]。此时基准5在位置1,左边是[1],右边是[8,9,10,7]。
- 对右边子数组[8,9,10,7]进行快速排序:
基准是7(最后一个元素)。分区后,所有元素都大于7,所以交换基准和第一个元素的位置,得到[7,9,10,8].
基准7在位置0,右边是[9,10,8].
- 对右边子数组[9,10,8]排序:
基准是8。分区后,所有元素都大于8,交换后得到[8,10,9]. 基准在位置0,右边是[10,9].
- 对右边子数组[10,9]排序:
基准是9。分区后,交换得到[9,10]. 基准在位置0,右边是[10].
此时右边的所有子数组处理完毕,合并后整个数组为[1,5,7,8,9,10].
优缺点
优点:
- 原地排序,空间复杂度 O(log n)。
- 适合大规模数据,实际运行速度快,常数因子小。
缺点:
- 不稳定排序,在特定情况下(如数据已经有序或逆序)可能会表现不佳。
- 对基准元素选择敏感。
- 递归调用栈可能导致栈溢出。
平均时间复杂度为O(nlog2n),最好的情况下是 O(nlog2n),不稳定排序。
平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 |
---|---|---|---|
O(nlog2n) | O(nlog2n) | O(n²) | O(1) |