对数组常用排序快速排序的随机化(详细)

文章讨论了快速排序在遇到最坏情况时会面临O(n^2)的时间复杂度,导致效率降低甚至超时。为解决这一问题,提出了通过随机选择基准数的方法来改进,使用rand()函数在数组范围内生成随机下标,从而防止特定数组顺序导致的最坏情况,提高了算法的平均性能。
摘要由CSDN通过智能技术生成

快速排序是我们在算法里最常用的基础排序方法之一。

但我们在力扣等网站做题时使用快速排序时依旧可能会碰到有几组用例超时的情况,这可能是碰到了最坏情况。

出现最坏情况时,我们的时间复杂度为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");
}

在增加了随机性之后,我们就不怕我们需要排序的数组出现特殊组合导致的最坏情况了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值