快排递归、迭代的实现和两种优化方法

news2024/12/23 19:27:09

目录

快速排序

实现代码

 时间复杂度

快排的优化

随机选择策略

三位取中法

非递归的快排


快速排序

        快速排序算法是基于分治策略的一个排序算法,其基本思想是对于输入的子数组进行分解、递归求解,最后合并。

分解:以数组中左边第一个数作为基准元素,将数组划分为三段,nums[left,mid-1],nums[mid],nums[mid+1,right],第一段中所有元素都比nums[mid](这就是那个基准数)小,第三段中所有元素都大于等于基准数。

递归求解:递归调用快排分别对nums[mid]的左右两段分别排序

合并:当每一小段就地排序都排好序后,整个数组就已经排完了

实现代码

void Print(int* nums, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%-5d", nums[i]);
	}
	printf("\n");
}
int Partition(int* nums,int left,int right)
{
	int l = left, r = right;
	int tmp = nums[l];
	while (l < r)
	{//确保l,r不错位每个都要判断l<r
		while (l<r && nums[r]>tmp)r--;//先找右边比tmp小的值
		if (l < r)nums[l] = nums[r];
		while (l< r && nums[l]<= tmp)l++;//在找左边比tmp大的值
		if (l< r)nums[r] = nums[l];
	}
	//l,r指针重合
	nums[l] = tmp;
	return l;
}
void QuickSort(int* nums, int left ,int right)
{
	if(left<right)
	{
		int mid = Partition(nums, left, right);//划分函数
		QuickSort(nums, left, mid - 1);
		QuickSort(nums, mid + 1, right);
	}
}

划分时一定要先从右边开始扫描 

 时间复杂度

         一般在问题规模为n时时间复杂度T(n)= Ο(nlogn)。最坏情况,数据从小到大或从大到小有序时T(n) =  Ο(n^2) 。


快排的优化

随机选择策略

      在快排的每一步当数组还没有被划分时,在数组中随机选出一个元素作为划分基准,划分基准随机则划分是比较对称的。用stand()指定一个随机起始点,然后将随机数模数组长度。因为这个right - left是相对位置的长度,但使用的下标rapos必须为绝对位置的下标,所以需要+left。

        将随机选择的基准值交换到第一个位置,然后再使用划分函数。

int RandomPartition(int* nums, int left, int right)
{
	srand(time(nullptr));//随机种子
	int rapos = rand() % (right - left + 1)+left;//取模
	std::swap(nums[left], nums[rapos]);//交换两个下标的值
	return Partition(nums, left, right);
}

三位取中法

        left ,right ,mid三个位置的元素取中间大小的元素作为基准值。如nums[left] = 12,nums[mid]=8,nums[right]=10;则取nums[right]作为基准。

struct Index
{
	int val;
	int index;
};
int MedionThree(int* nums, int left, int right)
{
	int mid = left + (right - left >> 1);
	struct Index idx[] = { {nums[left],left},{nums[mid],mid},{nums[right],right} };
	for (int i = 0; i < 3; i++)//找到中间大的数放到数组头做基准值
	{
		switch(i)
		{
		case 0:
			if ((idx[i].val - idx[1].val) * (idx[i].val - idx[2].val) < 0) 
			{ std::swap(nums[idx[i].index], nums[left]); }
			break;
		case 1:
			if ((idx[i].val - idx[0].val) * (idx[i].val - idx[2].val) < 0)
			{
				std::swap(nums[idx[i].index], nums[left]);
			}
			break;
		case 2:
			if ((idx[i].val - idx[0].val) * (idx[i].val - idx[1].val) < 0)
			{
				std::swap(nums[idx[i].index], nums[left]);
			}
			break;
		}
	}
	return Partition(nums, left, right);
}

非递归的快排

算法递归的部分在于划分后将不同子串输入进去继续划分。非递归时可以将子串的边界装在队列中,之后依次取出作为划分的左右边界。当队列为空,即划分完所有的以后结束。

void QuickSort(int* nums, int left, int right)
{
	queue<int> qu;//队列
	qu.push(left);
	qu.push(right);
	while(!qu.empty())
	{
		int sleft = qu.front(); qu.pop();//取队头,出left
		int sright = qu.front(); qu.pop();
		int mid = Partition(nums, sleft, sright);
		if (sleft < mid - 1)//左边有一个以上元素,仍需划分
		{
			qu.push(sleft);
			qu.push(mid - 1);
		}
		if (mid + 1 < right)
		{
			qu.push(mid + 1);
			qu.push(sright);
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运行flutter doctor命令检测环境是否配置成功报错及解决方案

/** 运行flutter doctor命令检测环境是否配置成功&#xff0c;报如下错误**/ 1. cmdline-tools component is missing & Android licenses status unknown 1.1.安装cmdline-tools 1.2.配置android-licenses 运行命令flutter doctor --android-licenses&#xff0c;提示…

封装一个帧动画组件,使用的是精灵图

我写的是淘宝小部件&#xff0c;限制很多&#xff0c;用的是精灵图&#xff0c;说下大概思路&#xff0c;主要是通过背景图片的X Y轴去控制&#xff0c;首先创建一个组件 例&#xff1a; 然后在props定义需要的参数&#xff0c;可通过父组件传递修改 需要传入精灵图地址、单…

【云原生】Prometheus监控docker容器

部署node-exporter用于搜集硬件和系统信息 // 全部主机都要做 docker run -d -p 9100:9100 -v /proc:/host/proc -v /sys:/host/sys -v /:/rootfs --nethost prom/node-exporter --path.procfs /host/proc --path.sysfs /host/sys --collector.filesystem.ignored-mount-point…

Windows系统pagefile.sys删除、移动

背景 在使用windows系统中通常会发现c盘系统盘容量和实际容量不符。以至于你以为还有几十个G的空间&#xff0c;但操作程序时会出现空间不足的情况 。 例如以下错误&#xff1a; # There is insufficient memory for the Java Runtime Environment to continue. # Native memo…

【六】Netty Google Protobuf 编解码

Netty Google Protobuf 编解码Google Protobuf 介绍Protobuf 的入门Protobuf 开发环境搭建Protobuf 下载创建.proto文件第五节的 对应实体&#xff08;SubscribeReq&#xff0c;SubscribeResp &#xff09;SubscribeReq.proto 文件SubscribeResp.proto利用命令生成对应的java文…

详解c++---string模拟实现

这里写目录标题前言准备工作构造函数析构函数迭代器的实现插入数据有关的函数实现reservepush_backoperatorappendinserterasefindresize[ ]clear>>>>新式拷贝构造函数新式赋值重载前言 在前面的文章里我们学习了c中string的用法&#xff0c;那么这篇文章我们将带…

Vue的双向绑定(数据劫持)

双向绑定所谓的双向绑定其实就是&#xff0c;ui或者数据有一方做了修改&#xff0c;那么另外一个也会随着改变。简单来说&#xff0c;视图驱动数据&#xff0c;同时数据也能驱动视图。视图驱动数据&#xff0c;只需要绑定事件。数据驱动视图&#xff0c;则需要去对数据做监听&a…

DC-DC PCB layout经验-含走线宽度和载流量表格

在DC-DC芯片的应用设计中&#xff0c;PCB布板是否合理对于芯片能否表现出其最优性能有着至关重要的影响。不合理的PCB布板会造成芯片性能变差如线性度下降&#xff08;包括输入线性度以及输出线性度&#xff09;、带载能力下降、工作不稳定、EMI辐射增加、输出噪声增加等&#…

不同Nodejs版本的TypeScript的建议配置

Node Target Mapping microsoft/TypeScript Wiki GitHubTypeScript is a superset of JavaScript that compiles to clean JavaScript output. - Node Target Mapping microsoft/TypeScript Wikihttps://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping以上是tsc…

SpringBoot+Vue项目知识管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…

macOS 安装 Frama-C 及使用

操作系统&#xff1a;macOS 12.6 Monterey 官网安装指导&#xff1a;Get Frama-C 一、操作与避坑 &#x1f573;️ 1、macOS 包管理绕不开 Homebrew 工具&#xff0c;确保安装好。 2、安装 Frama-C 的必要依赖 brew install opam gmp gtk gtksourceview libgnomecanvas在安装…

MATLAB-最大值与最小值

在MATLAB中&#xff0c;用于计算最大值的函数是max函数&#xff0c;用于计算最小值的函数是min函数&#xff0c;其调用格式如下。Bmax(A) %计算最大值 &#xff0c;若A为向量&#xff0c;则计算并返回向量中的最大值;若A为矩阵&#xff0c;则计算并返回%一个含有各列最大值的行…

从0到1完成一个Vue后台管理项目(九、引入Breadcrumb面包屑,更改bug)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

ansible(第四天)

三&#xff1a;编写playbook 1.Ansible playbook 临时命令可以作为一次性对一组主机运行简单的任务。不过&#xff0c;若要真正发挥Ansible的力量&#xff0c;需要了解如 何使用playbook可以轻松重复的方式对一组主机执行多项复杂的任务。 play是针对对清单中选定的主机运行…

汽车电子系统网络安全组织管理

声明 本文是学习GB-T 38628-2020 信息安全技术 汽车电子系统网络安全指南. 下载地址 http://github5.com/view/764而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 汽车电子系统网络安全组织管理 6.1 组织机构设置 组织应高度重视网络安全&#xff0c…

基于Prometheus+Grafana搭建监控平台(Windows/Linux环境exporter部署)

1. 介绍 1.1 Prometheus是什么?Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云计算基金会…

【从零开始学习深度学习】43. 算法优化之Adam算法【RMSProp算法与动量法的结合】介绍及其Pytorch实现

Adam算法是在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均 【可以看做是RMSProp算法与动量法的结合】。 目录1. Adam算法介绍2. 从零实现Adam算法3. Pytorch简洁实现Adam算法--optim.Adam总结1. Adam算法介绍 Adam算法使用了动量变量vt\boldsymbol{v}_tvt​和RMS…

LVGL官方UI设计软件——SquareLine Studio micropython 使用简单测评

经常去LVGL官网逛的人一定都知道这个软件&#xff0c;作为官方的亲儿子&#xff0c;使用体验如何呢&#xff0c;我简单体验了一周左右&#xff0c;简单做个测评&#xff0c;本测评仅代表我个人意见&#xff0c;并且仅限micropython的使用体验&#xff01; 首先是价格&#xff0…

TCP报文段(segment)首部格式

TCP传给IP的数据单元称作TCP报文段或简称为TCP段&#xff08;TCP segment&#xff09;。 IP传给链路层的数据单元称作IP数据报(IP datagram)。 通过以太网传输的比特流称作帧(Frame)。 逐层封装&#xff1a; 源端口号发送端端口号&#xff0c;字段长16位&#xff08;2字节&…

计算机网络第二章

物理层的基本概念物理层的作用&#xff1a;物理层解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。物理层的主要任务&#xff1a;确定与传输媒体接口有关的一些特性 &#x1f51c;本质&#xff1a;定义一些固定标准物理层的四大特性&a…