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

news2024/11/24 5:59:08

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自增1
        if(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都自增1
            lt++;
            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.coloradmin.cn/o/1828179.html

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

相关文章

【AI实践】Ollama本地安装大模型服务

Ollama安装运行 安装与配置 Download Ollama 安装默认在C盘&#xff0c;成功后&#xff0c;window任务栏图标会有Ollama Logo 为了不占用C盘更大的空间&#xff0c;修改模型下载路径&#xff0c;修改环境变量 下载模型 由于我电脑是第六代Intel&#xff0c;集显&#xff0c;…

北斗三代一体式数传终端短报文

北斗三代一体式数传终端短报文M20C-V30针对船载通信和导航应用推出的一款支持北斗 RDSS/RNSS 功能的船载一体机。北斗数传终端内部集成了北斗多频天线、射频、基带以及主控等功能单元&#xff0c;可实现 RDSS 定位、短报文通信和 RNSS 导航定位等功能。M20C-V30型北斗数传终端体…

万事开头难——Java实现俄罗斯小方块【第一步】

目录 技术实现&#xff1a; 1.初始化游戏窗口&#xff1b; 1.1 什么是窗口&#xff1a; 1.2 Swing 1.3 JFrame创建窗口&#xff1a; 1.3.1创建窗口的逻辑 1.3.2.设置简单的页面 1.3.3.优化 1.3.4.设置标题 1.4 创建游戏窗口 技术实现&#xff1a; 1.初始化游戏窗口&am…

「茶桁 AI 秘籍-CV 篇」预告

Hi, 大家好。 我是茶桁。 咱们的《茶桁的 AI 秘籍》系列距离上一个系列课程《人工智能 BI 核心》已经有一段时间了&#xff0c;终于有时间可以写 CV 部分的课程&#xff0c;主要也是最近一段时间我确实有点忙不过来。 那么咱们 CV 的课程会有一些变化&#xff0c;就是会改为收…

Spring MVC详解(上)

一、Spring MVC初步认识 1.1介绍 Spring MVC是Spring Framework提供的Web组件&#xff0c;全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能 Java Web开发者必须要掌握的技术框架 1.2MVC是什么 MVC是一种软件架构思想…

如何区分人工智能生成的图像与真实照片(下)

4 功能上的不合理性 AI 生成的图像往往会因为缺乏对现实世界物体结构和相互作用的了解&#xff0c;而产生各种功能不合理之处。这些不合理之处主要表现在以下几个方面&#xff1a; 4.1 构图不合理 物体关系不合逻辑: AI 生成的图像中&#xff0c;物体和人物之间的关系可能不符…

Sigir2024 ranking相关论文速读

简单浏览一下Sigir2024中与ranking相关的论文。不得不说&#xff0c;自从LLM大热后&#xff0c;传统的LTR方向的论文是越来越少了&#xff0c;目前不少都是RAG或类似场景下的工作了&#xff0c;比如查询改写、rerank等。 文章目录 The Surprising Effectiveness of Rankers Tr…

MySQL查询练习题1.平均工资2.查询各部门的总薪水3.查询总薪水排名第二的部门4.查询姓名重复的员工信息5.查询各部门薪水大于900的男性员工的平均薪水

创建一个员工表emp&#xff0c;包含字段&#xff1a;姓名name&#xff0c;性别sex&#xff0c;部门depart&#xff0c;工资salary create table emp(name varchar(30) not null,sex varchar(30) not null,depart int not null,salary int not null); 插入数据打印为 mysql>…

AtCoder Beginner Contest 358 A~E(F,G更新中...)

A.Welcome to AtCoder Land 题意 给出两个字符串 S , T S, T S,T&#xff0c;请你判断是否满足&#xff1a; 字符串 S S S为AtCoder 字符串 T T T为Land 分析 输入后判断即可 代码 #include<bits/stdc.h> using namespace std; void solve() {string s, t;cin &g…

HumanPlus——斯坦福ALOHA团队开源的人形机器人:先影子学习技术收集数据,后上模仿学习和RL

前言 今天只是一个平常的日子&#xff0c;不过看到了两篇文章 一篇是《半年冒出近百家新公司&#xff0c;「具身智能」也有春天》 我看完之后转发到朋友圈&#xff0c;并评论道&#xff1a;让机器人翻一万个后空翻&#xff0c;不如让机器人打好一个螺钉&#xff0c;毕竟在目前阶…

element--el-table添加合计后固定列x轴滚动条无法滚动问题

效果图 改变固定列滚轮高度问题 解决文章 解决方案 使用到的参数 pointer-events 属性用来控制一个元素能否响应鼠标操作&#xff0c;常用的关键字有 auto 和 none pointer-events: none; 让一个元素忽略鼠标操作 pointer-events: auto; 还原浏览器设定的默认行为 代码演示 添…

Mysql学习笔记-进阶篇

一、存储引擎 1、MYSQL体系结构 连接层、服务层、引擎层、存储层&#xff1b; 2、存储引擎简介 存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是库的&#xff0c;所以存储引擎也可被称为表类型。 1&#xff09;在创…

天阳科技集团北京卡洛其项目管理专家李先林受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 天阳科技集团北京卡洛其项目管理专家李先林先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“应用软件项目管理标准化实践探讨”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1…

.net 调用海康SDK的常用操作封装

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不仅…

(南京观海微电子)——TFT激光修复技术

激光在显示面板修复方面的应用 液晶面板包括TFT玻璃、CF玻璃、面板以及后段模块组装等一系列工艺制作过程。每段过程中都会产生一定的缺陷&#xff0c;例如亮点、暗点、闪点、碎亮点等。这些缺陷会导致部分区域显示不良&#xff0c;但是我们可以通过暗点化、亮点化、ITO隔离、…

【Linux】pycharmgit相关操作

目录 1. git安装配置2. 相关内容3. pycharm连接远程仓库3.1 配置3.2 clone远程仓库3.3 本地仓库上传远程 4. 分支管理4.1 更新代码4.2 新建分支4.3 分支合并4.4 代码比对 5. 版本管理6. 命令行操作6.1 配置git6.2 基础操作6.3 分支操作 1. git安装配置 下载链接&#xff1a;官…

多模态大模型:基础架构

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则…

如何进行文件映射

创建一个文件WebMvcConfig package com.itheima.config;import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.…

Retrofit 注解参数详解

添加依赖 implementation com.squareup.retrofit2:retrofit:2.9.0 implementation com.squareup.retrofit2:converter-gson:2.9.0 初始化Retrofit val retrofit Retrofit.Builder().baseUrl("http://api.github.com/").addConverterFactory(GsonConverterFactory…

深度遍历-求矩阵最长递增路径

一、问题描述 二、解题思路 和深度遍历-求岛屿数量的思路一致&#xff0c;不过这里不需要设置判断是否产生访问过的boolean二维数组了&#xff0c;因为在这个题目里面是求递增序列&#xff0c;下一个元素只有比当前元素大才会往前走&#xff0c;即使在回头检查时&#xff0c;发…