快速排序是我们在算法里最常用的基础排序方法之一。
但我们在力扣等网站做题时使用快速排序时依旧可能会碰到有几组用例超时的情况,这可能是碰到了最坏情况。
出现最坏情况时,我们的时间复杂度为O(n2),此时快速排序的效率最低,在做题时非常容易超时
关于最坏情况,CSDN里有很多文章的讲解,我就不多赘述了,今天我们重点讨论的是如何通过快速排序的随机化来避免这个最坏情况。
这里附上未随机化的快速排序函数
#include<stdio.h>
void Quick_sort(int nums[], int left, int right)
{
int i, j, temp, tp;
temp = nums[left];
i = left;
j = right; //采用最左边的数作为基准数 ,定义双指针
if (left > right)
return;//左右指针汇合后返回
while (i != j)
{
while (nums[j] >= temp && i < j)
j--;//如果基准数用的最左侧的数必须将右指针的循环放在前面
while (nums[i] <= temp && i < j)
i++;//将i,j两指针分别向另一端移动
if (i < j)
{
tp = nums[i];
nums[i] = nums[j];
nums[j] = tp;
}//将比j指向的基准数小的数与i指向的比基准数大的数交换
}
nums[left] = nums[i];
nums[i] = temp;
Quick_sort(nums, left, i - 1);
Quick_sort(nums, i + 1, right);//对i左侧,右侧的数组再次进行排序
}
void main()
{
int nums[10], i;
printf("please input 10 numbers:\n");
for (i = 0; i < 10; i++)
scanf_s("%d", &nums[i]);//输入十个数来进行测试(VS2022的输入要求用scanf_s,一般用scanf就好)
printf("The array is:\n");
for (i = 0; i < 10; i++)
printf("%-4d", nums[i]);//输出原数组进行对比
Quick_sort(nums, 0, 9);
printf("\nAfter sort the array is:\n");
for (i = 0; i < 10; i++)
printf("%-4d", nums[i]);//输出调用函数进行排序后的数组
printf("\n");
}
在上面的代码中我们固定选用数组中最左边的数作为基准数,接下来我们对代码进行修改,使基准数的选取改为数组中随机的一个数。
我们使用rand函数来生成随机数
举个栗子
如果我们想生成y到x之间的随机数
随机数int a = rand() % x(最大值) + y(最小值);
我们用这个随机数替换掉最左边的数:
int h = rand() % (end - begin + 1) + begin;
//定义一个h使其随机在第一个下标begin和最后一个下标end中取值
int temp = nums[begin];
nums[begin] = nums[h];
nums[h] = temp;
代码的实现:
#include<stdio.h>
#include<stdlib.h>//调用rand所需要的库函数
void Quick_sort(int* nums, int begin, int end)
{
if (end < begin)
return;
int i = begin;
int j = end;
int h = rand() % (end - begin + 1) + begin;//定义一个h使其随机在第一个下标begin和最后一个下标end中取值
int k = nums[h];
int temp = nums[begin];
nums[begin] = nums[h];
nums[h] = temp;//将数组中的随机数与数组中最左边的数互换
//这样我们下面的循环就不需要做出改变啦
while (i != j)
{
while (i < j && nums[j] >= nums[begin])
j--;
while (i < j && nums[i] <= nums[begin])
i++;
if (i < j)
{
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
nums[begin] = nums[i];
nums[i] = k;//之前用k来保存了所用的随机数的值
//现在把它赋给数组中下标为i的数
Quick_sort(nums, begin, i - 1);
Quick_sort(nums, i + 1, end);
}
void main()
{
int nums[10], i;
printf("please input 10 numbers:\n");
for (i = 0; i < 10; i++)
scanf_s("%d", &nums[i]);//输入十个数来进行测试(VS2022的输入要求用scanf_s,一般用scanf就好)
printf("The array is:\n");
for (i = 0; i < 10; i++)
printf("%-4d", nums[i]);//输出原数组进行对比
Quick_sort(nums, 0, 9);
printf("\nAfter sort the array is:\n");
for (i = 0; i < 10; i++)
printf("%-4d", nums[i]);//输出调用函数进行排序后的数组
printf("\n");
}
在增加了随机性之后,我们就不怕我们需要排序的数组出现特殊组合导致的最坏情况了。