随机快速排序
快速排序是一个经典的算法,它是基于比较排序中最快的算法之一,时间复杂度是O(N * logN)的,时间复杂度证明可以用master公式证明。但经典的快速排序会存在最坏的情况,会使得快速排序的时间复杂度退化到O(N2),这样快速排序也就失去了意义。因此我们为了避免出现最坏的情况,来引入随机一行为,每次的基准值是随机选取的 ,那么这样无论是什么数据都无法影响我们排序。那么随机快速排序的时间复杂度是O(N * logN),因为用了随机就不能用最好和最坏的时间复杂度来估计了,而要按照数学期望来估计它的时间复杂度。那么具体的证明过程,在算法导论-7.4.2有详细的数学证明,感兴趣的可以去看。
代码实现
这个随机快速排序是用了荷兰国旗问题优化过的。
//快速排序的改进避免最坏情况
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define N 100
typedef int ELEMENT;
void quickSort(ELEMENT *a, int low, int high);
void swap(ELEMENT *a, int low, int high);//交换a[low]和a[high]的值
int* partition(ELEMENT *a, int low, int high, ELEMENT key);//把a中low到high的数按照key分类,小于key的在左边,等于key的在中间,大于key的在右边
int main(int argc, char *argv[])
{
int a[N];
srand(time(NULL));
for (int i = 0; i < N; i++) {
a[i] = rand() % 100;
}
quickSort(a, 0, N - 1);
for (int i = 0; i < N; i++) {
printf("%d ", a[i]);
}
putchar('\n');
return 0;
}
void quickSort(ELEMENT *a, int low, int high)
{
int *p = NULL;//存储等于基准值的左右边界
if ( low >= high) {//如果只有一个值不用排序就直接结束排序
return ;
}
p = partition(a, low, high, a[low + rand() % (high - low + 1)]);//p指向等于基准值区间左右边界
quickSort(a, low, p[0] - 1);//只排小于基准值的部分
quickSort(a, p[1] + 1, high);//只排大于基准值的部分
free(p);//释放掉开辟的空间
}
void swap(ELEMENT *a, int low, int high)
{
ELEMENT t = 0;
t = a[low];
a[low] = a[high];
a[high] = t;
}
int* partition(ELEMENT *a, int low, int high, ELEMENT key)
{
int l = low;//代表等于key区间的左边界,或者是小于区间的下一个数
int r = high;//代表等于key区间的右边界,或者是大于区间的下一个数
int i = low;//从头开始遍历
while(i <= r) {//只要没有到大于区间
if (a[i] < key) {//下标i的数小于基准值,放在左边界里面
swap(a, l++, i++);//把左边界的后一个数和下标i的值交换,然后左区间扩张,然后去看下一个数
}
else if ( a[i] > key){//下标i的数大于基准值,放在右边界里面
swap(a, r--, i);//把右边界的前一个数和下标i的值做交换,然后右区间扩张,但i不能动,因为当前i的值还没有访问过
}
else {//下标i的数等于基准值,放在左右边界之间
i++;//直接加1
}
}
int *p = (int *)malloc(sizeof(int ) * 2);//存放等于区间的左右边界
p[0] = l;//等于区间左边界就是l
p[1] = r;//等于区间左边界就是r
return p;//返回等于key区间的左右边界
}
总结
在计算有随机行为算法的时间复杂度的时候,并且随机行为是算法中主要的部分时候,就不能用最坏的情况或者最好情况来计算时间复杂度因为不现实,而要用数学期望的时间复杂度。随机快速排序是一个经典的算法,也是必须要掌握的排序算法。快速排序用的还是分而治之的思想,因此分治法是很重要的。随机快速排序的时间复杂度是O(N * logN),额外空间复杂度是O(logN),假设每次都选在中间位置,那么最多递归logN层,所以额外空间复杂度是O(log N)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异