【数据结构】三路快速排序

1. 简介

传统快速排序用的是双路快速排序,即将大于基准值的部分放到基准值右侧,小于基准值的部分放到基准值左侧,但是这种算法面对过多的重复数据的数组,时间复杂度会增多,于是就有了三路快速排序的思想,其想法是将数组分为三个区间,假设选择数组的首元素作基准值e,则小于基准值e的数组放到基准值的左侧,等于基准值e的放到中间,大于基准值e的放到右边,即下图所示。

2. 思路

我们用i做循环遍历,遍历整个数组,我们选择数组的第一个元素做基准值e,如下图

left指针代表当前搜索区间的开始下标;
right指针代表当前搜索区间的结束下标;
lt(less than)指针代表小于e的区间的结束下标;
gt(greater than)代表大于e的区间的开始下标;
i指针指向当前待处理的元素;

记数组为nums,我们分三种情况讨论该算法,设当前nums[i]为x
(1)x和基准值e相等:
i直接向后移动1位,当前元素自动划分到等于e的区间

(2)x小于基准值e:
nums[lt+1]和nums[i]互换,并且lt和i都向前移动一位,此次互换,之前的数组都已经排好,左侧的都遍历过了,小于e的区间的元素都严格小于e,,而nums[lt+1]在交换前,是等于e区间的,所以和nums[i]互换后,nums[i]就是e,所以直接i自增1移动,因为交换后的nums[i]已经是等于e,所以向后移动,此时交换后,nums[lt+1]一定是严格小于e,所以小于e的区间的结束下标lt指针也得向后移动1个位置。

(3)x大于基准值e:
nums[gt-1]和nums[i]互换,gt向前移动1位,此时i不向前移动,因为交换过来的到底是大于基准值还是小于基准值还需要等待下次循环再判断,但是交换后nums[gt-1]已经是大于基准值e且gt是大于e的区间的开始指针,所以gt要减1来向前移动1位,这样也保证了遍历到最后,nums[i]如果还是大于e,最后nums[i]与首元素交换的时候就不合理了。

最后(i == gt的时候跳出循环),i会在等于e的区间的最后,我们要把nums[i]与nums[left]互换,使得等于e的区间里的元素全是重复的e,情况(3)中已经保证nums[i]不会大于e,情况(1)也保证nums[i]不会等于e
经过一趟三路快速排序的划分后,和传统的双路快速排序类似,我们要分别在小于e和大于e的区间上继续进行三路快速排序的划分

3. 代码实现(C语言)

思路在注释中

//生成从x到y的整数随机数
int getIntRandom(int x, int y)
{// 传入时间戳,生成伪随机数srand((unsigned int)time(NULL));return (int)(x + (rand() % (y - x + 1)));
}
//三路快速排序,返回lt(小于e的区间的结束下标)和gt(大于e的区间的开始下标)
//以长度为2的数组的形式返回lt和gt
void divide3(int* nums, int left, int right)
{//left超过right,递归结束if (left >= right) {return;}//随机选择一个下标做基准值的元素的下标(不做随机化处理,不能过长度很长的测试用例)int rand_index = getIntRandom(left, right);printf("%d\n", rand_index);//基准值int pivot = nums[rand_index];//交换元素用的临时遍历int temp = 0;//交换nums[rand_index]与nums[left],为了方便下面的交换//这样交换后还是等价于首元素做基准值temp = nums[rand_index];nums[rand_index] = nums[left];nums[left] = temp;//注意到,如果选择首元素做基准值,那么lt最开始就是left+1(对应首元素下标)//因为lt(less than)指针代表小于e的区间的结束下标int lt = left;//gt默认从最右侧+1开始,因为假设最开始大于e的区间是无限大//gt无需担心越界,因为我们遇到nums[i]大于e的情况,交换的是nums[i]与nums[gt-1]int gt = right + 1;//i从left + 1开始,因为首元素是基准值,遍历首元素后面的元素int i = left + 1;//循环结束的条件是i和gt指向同一个元素,此时i左侧最近的区间是等于e的区间,右侧是大于e的区间,完成了一轮三路快速排序while(i < gt){//如果当前元素和基准值相等,i自增1if(nums[i] == pivot){i++;}//如果当前元素小于基准值else if(nums[i] < pivot){//nums[lt+1]和nums[i]互换temp = nums[i];nums[i] = nums[lt+1];nums[lt+1] = temp;//lt和i都自增1lt++;i++;}//如果当前元素大于基准值else{//nums[gt-1]和nums[i]互换temp = nums[i];nums[i] = nums[gt-1];nums[gt-1] = temp;//i无需自增1,留着判断换过来的数//gt自减1,因为多了一个大于e的数,要向左扩大大于e的数组区间gt--;}}//交换nums[lt]与nums[left]temp = nums[lt];nums[lt] = nums[left];nums[left] = temp;//递归小于e和大于e的区间divide3(nums, left, lt-1);divide3(nums, gt, right);
}
int* sortArray(int* nums, int numsSize, int* returnSize) {divide3(nums, 0, numsSize - 1);*returnSize = numsSize;return nums;
}

提交结果:

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

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

相关文章

一个在C#中集成Python的例子

一个在C#中集成Python的例子。在C#中可以执行Python脚本&#xff0c;在Python中也可以调用C#宿主中的功能&#xff08;clr.AddReference(Business)&#xff09;。 文件说明 Debug为执行目录 Mgr.exe为执行文件 Py\init.py为python初始化脚本 Py\Lib.zip为python需要的模块&…

企业化运维(2)_nginx

###1.nginx源码安装部署### ###2.平滑升级### &#xff08;1&#xff09;版本升级 当服务器在运行时&#xff0c;需要升级的情况下&#xff0c;平滑升级即就是不断开服务器就可以进行升级&#xff0c;最大限度保证数据的完整性。 下载nginx新版本软件&#xff0c;正常执行./c…

蔡崇信“预言”:微软与OpenAI未来极有可能会分道扬镳

近日&#xff0c;在美国投行摩根大通于上海举行的第二十届全球中国峰会上&#xff0c;阿里巴巴集团联合创始人、董事局主席蔡崇信与摩根大通北亚区董事长兼大中华区投资银行业务副主席关金星&#xff08;Kam Shing Kwang&#xff09;进行了一场精彩对话。蔡崇信深入分享了他对公…

下载站名文件

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 得到了请求地址与请求参数后&#xff0c;可以发现请求参数中的出发地与目的地均为车站名的英文缩写。而这个英文缩写的字母是通过输入中文车站名转换…

Linux 文件的权限信息解读 chmod修改权限 数字序号表示权限

ls -l #列出当前文件 显示详细信息 drwxr-xr-x. 2 dpc test 6 Jun 15 07:45 test.txt共分为三部分 drwxr-xr-x.&#xff1a;表示文件和文件夹的权限信息dpc &#xff1a;文件&#xff0c;文件夹所属的用户test &#xff1a; 文件和文件夹所属的用户组 drwxr-xr-x 解读 d表示为…

hugo-magic主题使用教程(一)

前提条件 以下教程以windows10为例操作终端使用git bash魔法上网的前提下 下载hugo https://github.com/gohugoio/hugo/releases/download/v0.127.0/hugo_extended_0.127.0_windows-amd64.zip解压到任意目录,然后将目录添加到系统环境变量 如图 (windows)打开cmd 输入 hugo …

【CTS】android CTS测试

android CTS测试 1.硬件准备2. 软件准备3. 下载 CTS3.1 cts3.2 解压 CTS 包&#xff1a; 4 配置adb fastboot5 检查 Java 版本6 安装aapt26.1 下载并安装 Android SDK6.2 找到 aapt2 工具6.3 配置环境变量 7. 准备测试设备8. 运行 CTS 测试8.1 启动 CTS&#xff1a; 9. 查看测试…

Java面试八股之子类可以从父类继承哪些内容

Java子类可以从父类继承哪些内容 Java子类可以从父类继承以下内容&#xff1a; 属性&#xff08;Fields/Variables&#xff09;&#xff1a; public&#xff1a;子类可以继承父类所有的public修饰的属性。 protected&#xff1a;子类可以继承父类所有的protected修饰的属性…

uniapp中unicloud接入支付宝订阅消息完整教程

经过无数次的尝试,终于还是让我做出来了 准备工作 设置接口加签方式 使用支付宝小程序订阅消息,首先要设置接口加签方式,需要下载支付宝开放平台密钥工具,按照步骤生成秘钥,然后按照支付宝设置密钥加签方式添加接口加签方式。 有一点需要注意的,因为要在云函数中使用,…

STM32定时器篇——Systick定时器的使用(实现delay延时函数)

一、Systick定时器的简介&#xff1a; Systick定时器就是系统滴答定时器&#xff0c;一个24 位的倒计数定时器对于CM3,CM4内核芯片&#xff0c;都有Systick定时器。当Systick计到0时&#xff0c;将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中…

AI数据分析:根据Excel表格数据进行时间序列分析

ChatGPT中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个Python脚本编写的任务&#xff0c;具体步骤如下&#xff1a; 读取Excel表格&#xff1a;"F:\AI自媒体内容\AI行业数据分析\toolify月榜\toolify2023年-2024年月排行榜汇总数据.xlsx"…

如何设计网站

设计网站是一个复杂而又有趣的过程。一个好的网站设计不仅可以吸引用户的注意力&#xff0c;还能提供良好的用户体验。下面我将分享一些关于如何设计网站的基本原则。 首先&#xff0c;需要明确网站的目标和受众。在设计网站之前&#xff0c;你应该明确你的网站的目标是什么。你…

ROS-SLAM雷达

使用前准备工作 1、新建工作空间、编译功能包 以建立名字为rplidar_ws为例&#xff0c;终端输入 mkdir rplidar_ws cd rplidar_ws mkdir src cd src catkin_init_workspace rplidar_ros功能包&#xff1a;git下载。 https://github.com/Slamtec/rplidar_ros/ 然后把解压的…

Linux-Tomcat服务配置到系统服务

目录 前言一、系统环境二、配置步骤step1 了解环境的安装路径step2 配置生成tomcat.pid文件step3 配置tomcat.service文件 三、测试systemctl命令管理Tomcat服务3.1 systemctl命令启动Tomcat服务3.2 systemctl命令查看Tomcat服务3.3 systemctl命令关闭Tomcat服务3.4 systemctl命…

【python基础实例】从文件命名中提取特定信息(数字、字母等)

【python基础实例】从文件命名中提取特定信息&#xff08;数字、字母等&#xff09; 在处理文件和数据时&#xff0c;我们经常需要从文件名中提取特定的信息&#xff0c;如日期、序号或项目标识符。Python提供了强大的字符串处理功能&#xff0c;可以轻松完成这些任务。本文将…

Python 学习 第二册 第12章 图形界面

----用教授的方法学习。 目录 12.1 创建 GUI 示例应用程序 12.1.1 初探 12.1.2 布局 12.1.3 事件处理 12.1.4 最终的程序 12.1 创建 GUI 示例应用程序 这个微型文本编辑器的需求如下。 让用户能够打开指定的文本文件。 让用户能够编辑文本文件。 让用户能够保存文本…

浪潮信息MUPR自研专利 保障服务器内存运行的可靠性和高效性

在数字化转型的大潮中&#xff0c;服务器作为支撑企业业务运行的核心设备&#xff0c;其稳定性和可靠性显得尤为重要。然而&#xff0c;传统的内存故障预警修复技术往往存在反应滞后、误报率高等问题&#xff0c;难以满足日益增长的数据处理和存储需求。针对这一问题&#xff0…

C++初学者指南第一步---4.基本类型

C初学者指南第一步—4.基本类型 文章目录 C初学者指南第一步---4.基本类型1.变量声明2.快速概览Booleans 布尔型Characters 字符型Signed Integers 有符号整数Unsigned Integers 无符号整数Floating Point Types 浮点数类型 3.Common Number Representations 常用的数字表示常用…

【数据结构】——常见排序

文章目录 一、 冒泡排序二、 选择排序三、插入排序四、 快速排序1. hoare版本2. 优化版本3. 前后指针法4. 非递归版本 五、 堆排序六、 希尔排序七、 归并排序1. 递归版本2. 非递归版本 八、 计数排序 在开始之前先准备一个交换数据的函数&#xff0c;排序会经常用到 //交换位置…

银河麒麟系统安装

新建虚拟机 选择典型下一步&#xff1a; 稍后安装操作系统 下一步 &#xff1a; 选择Linux Ubuntu 64位 下一步&#xff1a; 设置名称 选择一个虚拟机的位置进行下一步&#xff1a; 磁盘大小默认给20G 下一步&#xff1a; 点击完成 编辑虚拟机设置 点击CD/DVD(SATA) 使用IS…