首页 > 其他分享 >随机快速排序

随机快速排序

时间:2023-12-15 19:45:03浏览次数:31  
标签:基准值 int 复杂度 high 随机 排序 快速 low

快速排序是一个经典的算法,它是基于比较排序中最快的算法之一,时间复杂度是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);//把a中low到high的数分类,小于的在左边,等于的在中间,大于的在右边

int main(int argc, char *argv[])
{
	int a[N];
	
	srand(time(NULL));
	
	for (int i = 0; i < N; i++) {
		a[i] = rand() % 100; 
	}

	for (int i = 0; i < N; i++) {
		printf("%d ", a[i]);
	}
	putchar('\n');
	
	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 ;
	}
	
	swap(a, low + rand() % (high - low + 1), high);//随机从数组里面找一个数,和最后一个数做交换 
	p = partition(a, low, high);//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)
{
	int l = low - 1;//左边界从low的左边,因为是把最后一个当作基准值 
	int r = high;//右边界从high开始,因为基准值是最后一个 
	int i = low;//从头开始遍历 
	int key = a[high];//把基准值赋值 
	while(i < r) {//只要没有到右边界 
		if (a[i] < key) {//下标i的数小于基准值,放在左边界里面 
			swap(a, l + 1, i);//把左边界的前一个数和下标i的值交换 
			i++;//去下一个数 
			l++;//左边界扩张 
		}
		else  if ( a[i] > key){//下标i的数大于基准值,放在右边界里面 
			swap(a, r - 1, i);//把右边界的前一个数和下标i的值做交换
			r--;//右边界扩张,因为把一个没有访问的数移过来了,所有等下还要访问这个数看是在那个区间的,所以i不加1 
		}
		else {//标i的数等于基准值,放在左右边界之间 
			i++;//直接加1 
		}
	}
	swap(a, r, high);//把基准值和右边界交换位置 
	int *p = (int *)malloc(sizeof(int ) * 2);//存放等于区间的左右边界 
	p[0] = l + 1;//左边界就是l + 1 
	p[1] = r;//右边界刚刚交换了值,所以它的值一定是基准值 
	return p;//返回这个区间 
}

总结

在计算有随机行为算法的时间复杂度的时候,并且随机行为是算法中主要的部分时候,就不能用最坏的情况或者最好情况来计算时间复杂度因为不现实,而要用数学期望的时间复杂度。随机快速排序是一个经典的算法,也是必须要掌握的排序算法。快速排序用的还是分而治之的思想,因此分治法是很重要的。随机快速排序的时间复杂度是O(N * logN),额外空间复杂度是O(logN),假设每次都选在中间位置,那么最多递归logN层,所以额外空间复杂度是O(log N)。

标签:基准值,int,复杂度,high,随机,排序,快速,low
From: https://www.cnblogs.com/lwj1239/p/17904088.html

相关文章

  • 基于RT-Thread快速上手SD NAND 虚拟文件系统
    SDNAND也称之为贴片式TF卡,贴片式SD卡,采用标准的SDIO接口,兼容SPI接口。下图所示为CS新一代CSSDNANDNP1GCR01-AOW大小为128M,对比128M的SD卡,可以看到贴片SD卡尺寸更小,不要SD卡座,占用更小的PCB面积;也可以节省PCB板层数,2层板即可使用。而且兼容可替代普通TF卡/SD卡,硬件电路软......
  • 快速打印docker容器日志
    有的时候需要在服务器上查看日志信息。往往敲命令又太多,觉得麻烦,所以写了一个这个脚本。赋权之后,这个脚本里面丢到/usr/local/bin/下面。就可以在任何地方使用lgs,然后输入容器部分的名字。如果有多个输入序号就可以打印日志啦。#/bin/bashread-p"entername:"contain......
  • RV1126 快速启动
    一、硬件信息RV1126/RV1109系列芯⽚内置硬件解压缩模块--decom,可以极⼤得提升系统启动速度RV1126/RV1109内置⼀个MCU,MCU在SoC上电后就会快速启动,迅速初始化Camera和ISP,然后尽可能快得保存前⼏帧图像。RV1126支持快速启动的存储介质存储介质类型读取速度......
  • Sortable 拖拽排序组件实现原理
    如果想要实现拖拽排序功能,有很多现成的库可以供使用,比如Sortable.js(vuedraggable)、dnd-kit(react-dnd)等可以轻松帮助实现这一功能。本文的目标不是介绍如何使用这些库,而是手动实现一个简单版的Sortable组件。通过本文的阅读,您将深入了解拖拽排序的核心原理。使用模板使用Sor......
  • 排序
    1.从未排序序列中依次取出元素与已排序序列中的元素进行比较,将其放入已排序序列的正确位置上的方法,这种排序方法称为(插入排序)。插入排序基本思想:每一步将一个待排序的数据插入到前面已经排好序的有序序列中,直到插完所有元素为止。插入排序的代码实现:voidStraightSort(int*a......
  • 亚马逊鲲鹏系统可快速创建大量的买家账户
    在数字时代的浪潮中,人们总是在寻找更便捷、高效的方式来完成各种任务,而亚马逊鲲鹏系统的出现,无疑为那些渴望拥有大批量买家号的人提供了一个全新的可能性。在这个系统中,注册买家号变得轻而易举,只需准备好一些必要的资料,你就能够快速创建大量的买家账户。首先,为了顺利进行注册,你需要......
  • java之冒泡排序
    冒泡排序原理:从第一个数开始,和后面一个数比较大小,根据升序或者降序,看是否需要互换位置。每一轮会把1个数罗列到正确位置,经过数组长度-1轮比较,排序完成。比如:对数组{11,55,33,22,44}进行升序排列数组长度是5,需要经过5-1轮,每一轮需要比较5-当前轮次。publicc......
  • shell补-特殊玩法-生成随机字符串
    shell补-特殊玩法-生成随机字符串方法1:md5sum方法2:tr+/dev/urandom方法3:内置变量RANDOM;#方法1[root@localhostser]#opensslrand-base64108/54arQpCmQ12Q==[root@localhostser]##方法2必备[root@localhostser]#date+%N|md5sum###给日期加密;可以写其......
  • Java-常见的排序算法有哪些
    Java-常见的排序算法有哪些比较排序算法:冒泡排序(BubbleSort):过程:从左到右依次比较相邻的元素,如果顺序不对就交换它们,一轮比较会将最大的元素冒泡到末尾。优势:简单易懂,对于小型数据集表现较好。劣势:时间复杂度为O(n^2),性能相对较差。插入排序(InsertionSort):过......
  • Eolink Apikit「 零代码」快速发起 RPC 接口自动化测试
    RPC(RemoteProcedureCall)远程过程调用,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC的核心思想是将远程服务抽象成一个接口,客户端通过调用这个接口,就可以实现对远程服务的访问。EolinkApikit支持多协议,RPC、DUBBO、HTTP、REST、Websocket......