[排序算法] 如何解决快速排序特殊情况效率低的问题------三路划分

前言

        在[C/C++]排序算法 快速排序 (递归与非递归)一文中,对于快速排序的单趟排序一共讲了三种方法: hoare挖坑法双指针法 ,这三种方法实现的快速排序虽然在一般情况下效率很高,但是如果待排序数据存在大量重复数据,那这几种方法的效率就很低,而为了解决快速排序在这样特殊情况下效率低下的问题, 三路划分就可以完美解决

三路划分

思想:

        对于上述三种方法,其本质都是选定数组开头元素作特定值,让小的数据放左边,大的数据放右边。而三路划分顾名思义就是通过处理将数据分为三个部分 [小于特定值的部分   等于特定值的部分  大于特定值的部分] ,这样划分好后,只需要对小于特定值的部分和大于特定值的部分进行递归排序即可,中间的数据就不需要处理了,相比于上述三种方法效率提升很大,并且重复数据越多排序效率越快,当带排序数据全为重复数据时,时间复杂度甚至可以达到O(N)。

算法实现

首先我们定义一个cur指针指向begin的下一个元素,将begin开始所指元素定为关键值key

比较a[cur]与key的值,会出现三种情况

  1. 若a[cur]<key,交换a[begin]和a[cur], cur++, begin++
  2. 若a[cur]>key,交换a[end]和a[cur],end--
  3. 若a[cur]==key,cur++

重复比较操作,直到cur>end

[解释]:

为什么a[begin]和a[cur]交换后, cur要++, 而a[end]和a[cur]交换后,cur不和情况1一样++呢?

        因为a[end]和a[end]交换,目的是让大于key的值放到后面,而end所指元素我们不知道其与key的大小关系,所以下一次循环,还得判断其与key的关系才行,cur++会跳过这个元素。而begin初始所指元素就是关键值key, 当第一次找到比key小的数让两者交换,此时cur所指元素就是关键值,再仔细揣摩一下,只有小的数往左放的时候begin才会++,碰到大的数会把他往后放,放完还得比较当前cur所指的元素,碰到与key相同的元素不交换,cur往后走,这样我们会发现begin只会指向和key一样大的元素,所以交换完后,cur可以++。


单趟排序图解如下:

a[cur]<key,交换,cur++,begin++

a[cur]<key,交换,cur++,begin++

a[cur]==key, cur++

a[cur]==key, cur++

a[cur]>key,交换a[end]和a[cur],end--

a[cur]==key, cur++

a[cur]==key, cur++,此时cur>end,排序完成,将数据分为了三个部分

因为单趟排序排好后划分了三个部分,我们处理两边的部分需要返回两个值,所以就不单独封装三路划分的单趟排序了

代码如下:

void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

int GetMid(int* a, int begin, int end)
{
	int mid = (begin + end) / 2;
	if (a[begin] > a[mid])
	{
		if (a[mid] > a[end])
			return mid;
		else if (a[begin] > a[end])
			return end;
		else
			return begin;
	}
	else
	{
		if (a[begin] > a[end])
			return begin;
		else if (a[mid] > a[end])
			return end;
		else
			return mid;
	}
}

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;

	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);

    //由于begin和end要改变,提前保存,便于递归使用
	int left = begin;
	int right = end;

	int cur = begin + 1;
	int key = a[begin];

	while (cur <= end)
	{
		if (a[cur] < key)
		{
			swap(&a[cur], &a[begin]);
			begin++;
			cur++;
		}
		else if (a[cur] > key)
		{
			swap(&a[cur], &a[end]);
			end--;
		}
		else
		{
			cur++;
		}
	}
	QuickSort(a, left, begin - 1);
	QuickSort(a, end + 1, right);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

马蹄集oj赛(双周赛第十八次)

目录 幸运的3 打靶 照亮街道 九次九日九重色 寻找串 竹鼠的白色季节 捉迷藏 好的三连 三角数 买马 可怜的小码哥 花园浇水 高次方程 幸运的3 难度:黄金时间限制: 1秒四占用内存:128M 你有 n 个数&#xff0c;可以将它们两两匹配(即将两数首尾相连)&#xff0c;每个…

element中Table表格控件实现单选功能、多选功能、两种分页方式

目录 1、Table表格控件实现单选功能2、Table控件和Pagination控件实现多选和两种分页方式方法一&#xff1a;使用slice方法方法二&#xff1a;多次调用接口 1、Table表格控件实现单选功能 <template><div><!-- highlight-current-row 是否要高亮当前行 -->…

【史上最细教程】CentOS7 下载安装 RabbitMQ(两种方式:手动安装 / Docker安装)

文章目录 【史上最细教程】CentOS7 下载安装 RabbitMQ方式一&#xff1a;手动安装1.下载安装Erlang、RabbitMQ2.防火墙、安全组端口放行3.启动RabbitMQ服务4.浏览器用户登录5.配置文件查看(可略) 方式二&#xff1a;Docker安装1.安装Docker2.获取RabbitMQ镜像、创建容器3.浏览器…

synchronized锁

synchronized 类锁&#xff1a;给类的静态方法加上synchronized 关键字进行修饰&#xff0c; 锁的是当前类class&#xff0c;一个静态同步方法拿到锁&#xff0c;其他静态同步方法就会等待静态同步方法和普通同步方法间是没有竞争的 对象锁&#xff1a;给类的方法加上synchron…

权威外媒聚焦:Messari强调波场TRON在全球加密支付领域的引领作用

近日,金融时报、费加罗报及美联社等海外权威媒体就波场TRON 在全球加密支付领域的重要进展发布了相关报道。报道引述加密研究机构Messari 《Crypto Theses for 2024》年度报告,重点强调了波场TRON在推动全球加密货币支付尤其是稳定币USDT应用方面的显著成就。 报道提到,波场TR…

你的第一个C/S程序

目录 socket服务端代码客户端代码执行结果 socket socket基础知识 服务端代码 import socket import threading import timeMSG_LENGTH 64 DISCONNECTED !CONNECTION CLOSED connections 0#定义服务器地址 server_ip socket.gethostbyname(socket.gethostname()) server…

三城三奖!苏州金龙助力各地公共交通打造高品质线路

元旦前夕&#xff0c;由中国交通报社主办的绿色运输可持续发展座谈会暨2023年度“新能源公交高品质线路”经验交流会在京举行&#xff0c;来自全国各地的100余名行业管理部门、公交客运企业代表参会。会上同时评选出20条各具特色的“新能源公交高品质线路”及6家“我的公交我的…

后端主流框架-SpringMvc-day2

Java中的文件下载 2 文件下载 文件下载&#xff1a;就是将服务器&#xff08;表现在浏览器中&#xff09;中的资源下载&#xff08;复制&#xff09;到本地磁盘&#xff1b; 2.1 前台代码 前台使用超链接&#xff0c;超链接转到后台控制器&#xff0c;在控制器通过流的方式…

阿里云服务器(ECS云服务器)安装redis

前言&#xff1a; 笔者使用的是云服务器是阿里云的ECS服务器 这个服务器内核是Alibaba Cloud Linux 3。 使用的命令行工具为Alibaba Could Manager 命令行工具连接服务器这里就不多说了&#xff0c;如果没有用过的小伙伴可以去看阿里云的官方文档&#xff0c;很详细。 下面…

【51单片机系列】LCD1602液晶模块

本文是关于液晶显示屏的相关介绍。相对于静态数码管、动态数码管、LED点阵等&#xff0c;LCD1602液晶显示器能够显示更多的字符数字信息&#xff0c;并且也是常用的一种显示装置。 文章目录 一、LCD1602介绍1.1、LCD1602简介1.2、LCD1602常用指令1.3、LCD1602使用 二、LCD1602使…

[雷池WAF]长亭雷池WAF配置基于健康监测的负载均衡,实现故障自动切换上游服务器

为了进一步加强内网安全&#xff0c;在原有硬WAF的基础上&#xff0c;又在内网使用的社区版的雷池WAF&#xff0c;作为应用上层的软WAF。从而实现多WAF防护的架构。 经过进一步了解&#xff0c;发现雷池WAF的上游转发代理是基于Tengine的&#xff0c;所以萌生出了一个想法&…

SpringMVC-获取请求参数

1. 通过ServletAPI获取请求参数 /**** param request HttpServletRequest对象&#xff0c;直接作为形参传入方法&#xff0c;前端处理器就是一个Servlet* 所以前端处理器可以获得HttpServletRequest对象&#xff0c;并根据控制器方法的形参将对象传递给方法* re…

勒索事件急剧增长,亚信安全发布《勒索家族和勒索事件监控报告》

近期(12.15-12.21)态势快速感知 近期全球共发生了247起攻击和勒索事件&#xff0c;勒索事件数量急剧增长。 近期需要重点关注的除了仍然流行的勒索家族lockbit3以外&#xff0c;还有本周top1勒索组织toufan。toufan是一个新兴勒索组织&#xff0c;本周共发起了108起勒索攻击&a…

一文读懂$mash 通证的 “Fair Launch” 规则,将公平发挥极致

Solmash 是Solana生态中由社区主导的铭文资产LaunchPad平台&#xff0c;该平台旨在为Solana原生铭文项目&#xff0c;以及通过其合作伙伴SoBit跨链桥桥接到Solana的Bitcoin生态铭文项目提供更广泛的启动机会。有了Solmash&#xff0c;将会有更多的Solana生态的铭文项目、资产通…

【JUC的四大同步辅助类】

文章目录 一、CountDownLatch二、CyclicBarrier三、Semaphore四、Phaser 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、CountDownLatch CountDownLatch如同火箭发射&#xff0c;计数只能不断减减&#xff0c;当到达0时即发射 场景示例&#xff1…

elect函数可以设置等待时间,

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;贝叶斯滤波与Kalman估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能&#xff0c…

ssm基于BS的仓库在线管理系统的设计与实现论文

摘 要 如今的时代&#xff0c;是有史以来最好的时代&#xff0c;随着计算机的发展到现在的移动终端的发展&#xff0c;国内目前信息技术已经在世界上遥遥领先&#xff0c;让人们感觉到处于信息大爆炸的社会。信息时代的信息处理肯定不能用之前的手工处理这样的解决方法&#x…

OpenCV-Python(23):傅里叶变换

原理 傅里叶变换是一种数学变换&#xff0c;用于将一个函数&#xff08;在图像处理中通常是图像&#xff09;从时域&#xff08;空域&#xff09;转换到频域。它将函数表示为一系列正弦和余弦函数的和&#xff0c;用于分析信号的频率和相位信息。 傅里叶变换的原理是将一个连续…

【iOS安全】JS 调用Objective-C中WKWebview Handler的三种方式

有三种实现途径 1. WKScriptMessageHandler OC部分&#xff1a;注册并实现Handler 将OC中的方法"nativeMethod"注册为JavaScript Message Handler&#xff0c;从而WebView中的JavaScript代码可以调用该方法 // Register in Objective-C code - (void)setupWKWebVi…

No Magic—复杂机电产品系统架构开发套件

产品概述 CATIA Magic&#xff0c;原名MagicDraw&#xff0c;俗称No Magic&#xff0c;被达索收购后融入3DExperience产品协同研发管理平台中&#xff0c;形成更具协同体验的系统工程解决方案。该软件提供对SysML/UML/UAF语言的完整支持&#xff0c;提供独有的MagicGrid方法论&…