双路快速排序和三路排序算法
双路快速排序
一、概念及其介绍
双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将 <v 的元素放在索引i所指向位置的左边,而将 >v 的元素放在索引j所指向位置的右边,v 代表标定值。
二、适用说明
时间和空间复杂度同随机化快速排序。 对于有大量重复元素的数组,如果使用上一节随机化快速排序效率是非常低的,导致 partition 后大于基点或者小于基点数据的子数组长度会极度不平衡,甚至会退化成 O(n*2) 时间复杂度的算法,对这种情况可以使用双路快速排序算法。
三、过程
使用两个索引值(i、j)用来遍历我们的序列,将 <=v 的元素放在索引 i 所指向位置的左边,而将 >=v 的元素放在索引 j 所指向位置的右边,平衡左右两边子数组。
四、Java 实现分析
提供的Java代码实现了一个双路快速排序算法。以下是一些关键点的解释:
-
随机选择标定点:为了减少最坏情况的发生概率,算法首先随机选择一个标定点,并将其与数组的第一个元素交换位置。这一步有助于提高算法的平均性能。
-
分区函数 (
partition
):该函数实现了双路快速排序的核心逻辑。它使用两个指针i
和j
来遍历数组,根据元素与标定点的关系调整指针位置,并在必要时交换元素。最终返回标定点的正确位置。 -
递归排序:
sort
函数是一个递归函数,用于对数组的不同部分进行排序。每次调用partition
函数后,都会得到一个新的标定点位置,然后对左右两部分分别进行递归排序。 -
主函数 (
main
):这里创建了一个测试用例来验证算法的正确性和性能。通过生成一个大数组并调用sort
方法对其进行排序,可以观察到双路快速排序在大数据量下的高效表现。
package runoob;/*** 双路快速排序*/
public class QuickSort2Ways {//核心代码---开始private static int partition(Comparable[] arr, int l, int r){// 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivotswap( arr, l , (int)(Math.random()*(r-l+1))+l );Comparable v = arr[l];// arr[l+1...i) <= v; arr(j...r] >= vint i = l+1, j = r;while( true ){while( i <= r && arr[i].compareTo(v) < 0 )i ++;while( j >= l+1 && arr[j].compareTo(v) > 0 )j --;if( i > j )break;swap( arr, i, j );i ++;j --;}swap(arr, l, j);return j;}//核心代码---结束// 递归使用快速排序,对arr[l...r]的范围进行排序private static void sort(Comparable[] arr, int l, int r){if (l >= r) {return;}int p = partition(arr, l, r);sort(arr, l, p-1 );sort(arr, p+1, r);}public static void sort(Comparable[] arr){int n = arr.length;sort(arr, 0, n-1);}private static void swap(Object[] arr, int i, int j) {Object t = arr[i];arr[i] = arr[j];arr[j] = t;}// 测试 QuickSortpublic static void main(String[] args) {// 双路快速排序算法也是一个O(nlogn)复杂度的算法// 可以在1秒之内轻松处理100万数量级的数据// Quick Sort也是一个O(nlogn)复杂度的算法// 可以在1秒之内轻松处理100万数量级的数据int N = 1000000;Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);sort(arr);SortTestHelper.printArray(arr);}
}
三路排序算法
一、概念及其介绍
三路快速排序是双路快速排序的进一步改进版本,三路排序算法把排序的数据分为三部分,分别为小于 v,等于 v,大于 v,v 为标定值,这样三部分的数据中,等于 v 的数据在下次递归中不再需要排序,小于 v 和大于 v 的数据也不会出现某一个特别多的情况),通过此方式三路快速排序算法的性能更优。
二、适用说明
时间和空间复杂度同随机化快速排序。
三路快速排序算法是使用三路划分策略对数组进行划分,对处理大量重复元素的数组非常有效提高快速排序的过程。它添加处理等于划分元素值的逻辑,将所有等于划分元素的值集中在一起。
三、过程
我们分三种情况进行讨论 partiton 过程,i 表示遍历的当前索引位置:
(1)当前处理的元素 e=V,元素 e 直接纳入蓝色区间,同时i向后移一位。
(2)当前处理元素 e<v,e 和等于 V 区间的第一个位置数值进行交换,同时索引 lt 和 i 都向后移动一位
(3)当前处理元素 e>v,e 和 gt-1 索引位置的数值进行交换,同时 gt 索引向前移动一位。
最后当 i=gt 时,结束遍历,同时需要把 v 和索引 lt 指向的数值进行交换,这样这个排序过程就完成了,然后对 <V 和 >V 的数组部分用同样的方法再进行递归排序。
假设有一个数组 [2, 5, 2, 3, 7, 5, 5, 2]
,标定点 v
为 5
:
-
初始状态:
lt = 0
,i = 1
,gt = 8
- 数组:
[2, 5, 2, 3, 7, 5, 5, 2]
- 数组:
-
遍历过程:
- 当
i = 1
时,arr[i] == v
,i
向前移动一位:i = 2
- 当
i = 2
时,arr[i] < v
,交换arr[2]
和arr[lt+1]
,lt
和i
前进:lt = 1
,i = 3
- 数组:
[2, 2, 5, 3, 7, 5, 5, 2]
- 数组:
- 当
i = 3
时,arr[i] < v
,交换arr[3]
和arr[lt+1]
,lt
和i
前进:lt = 2
,i = 4
- 数组:
[2, 2, 3, 5, 7, 5, 5, 2]
- 数组:
- 当
i = 4
时,arr[i] > v
,交换arr[4]
和arr[gt-1]
,gt
向前移动:gt = 7
- 数组:
[2, 2, 3, 5, 5, 5, 7, 2]
- 数组:
- 当
i = 4
时,arr[i] == v
,i
向前移动一位:i = 5
- 当
i = 5
时,arr[i] == v
,i
向前移动一位:i = 6
- 当
i = 6
时,arr[i] > v
,交换arr[6]
和arr[gt-1]
,gt
向前移动:gt = 6
- 数组:
[2, 2, 3, 5, 5, 5, 2, 7]
- 数组:
- 当
i = 6
时,i == gt
,遍历结束。
- 当
-
最后,将标定点
5
与lt
指向的元素交换:lt = 3
- 数组:
[2, 2, 3, 5, 5, 5, 2, 7]
- 数组:
四、Java 实例代码
package runoob;/*** 三路快速排序*/
public class QuickSort3Ways {//核心代码---开始// 递归使用快速排序,对arr[l...r]的范围进行排序private static void sort(Comparable[] arr, int l, int r){if (l >= r) {return;}// 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivotswap( arr, l, (int)(Math.random()*(r-l+1)) + l );Comparable v = arr[l];int lt = l; // arr[l+1...lt] < vint gt = r + 1; // arr[gt...r] > vint i = l+1; // arr[lt+1...i) == vwhile( i < gt ){if( arr[i].compareTo(v) < 0 ){swap( arr, i, lt+1);i ++;lt ++;}else if( arr[i].compareTo(v) > 0 ){swap( arr, i, gt-1);gt --;}else{ // arr[i] == vi ++;}}swap( arr, l, lt );sort(arr, l, lt-1);sort(arr, gt, r);}//核心代码---结束public static void sort(Comparable[] arr){int n = arr.length;sort(arr, 0, n-1);}private static void swap(Object[] arr, int i, int j) {Object t = arr[i];arr[i] = arr[j];arr[j] = t;}// 测试 QuickSort3Wayspublic static void main(String[] args) {// 三路快速排序算法也是一个O(nlogn)复杂度的算法// 可以在1秒之内轻松处理100万数量级的数据int N = 1000000;Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);sort(arr);SortTestHelper.printArray(arr);}
}
排序算法衍生问题
本小节对本教程的排序算法做一个总结。
(1)归并排序和快速排序都使用了分治算法。
顾名思义,就是将原问题分割查能同等结构的子问题,之后将子问题逐一解决后,原问题也就得到了解决。
(2)逆序对的定义
如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对。我们可以使用本教程的归并思想求逆序对的数量。
(3)取数组中第 n 大的元素
并不需要对整个数组进行排序,使用快速排序的思路求数组中第 n 大元素算法复杂度为 O(n)。
相关文章:

双路快速排序和三路排序算法
双路快速排序 一、概念及其介绍 双路快速排序算法是随机化快速排序的改进版本,partition 过程使用两个索引值(i、j)用来遍历数组,将 <v 的元素放在索引i所指向位置的左边,而将 >v 的元素放在索引j所指向位置的…...

SQL server增删改查语句和实例
在 SQL Server 中,增删改查操作分别对应 INSERT、DELETE、UPDATE 和 SELECT 语句。以下是具体介绍及实例: 一、插入数据(INSERT) 语法: INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, val…...

强化学习_06_pytorch-PPO2实践(ALE/Breakout-v5)
一、环境适当调整 数据收集:RecordEpisodeStatistics进行起始跳过n帧:baseSkipFrame一条生命结束记录为done:EpisodicLifeEnv得分处理成0或1:ClipRewardEnv叠帧: FrameStack 图像环境的基本操作,方便CNN捕捉智能体的行动 向量空间reset处理修…...

《JVM第8课》垃圾回收算法
文章目录 1.标记算法1.1 引用计数法1.2 可达性分析法 2.回收算法2.1 标记-清除算法(Mark-Sweep)2.2 复制算法(Coping)2.3 标记-整理算法(Mark-Compact) 3.三种垃圾回收算法的对比 为什么要进行垃圾回收&…...

SpringBoot整合Freemarker(二)
if分支 语法: <#if condition>... <#elseif condition2>... <#elseif condition3>... <#else>... </#if> 例子: <#if x 1>x is 1 </#if> --------------------------------- <#if x 1>x is 1 <…...

element plus el-form自定义验证输入框为纯数字函数
element plus 的el-form 使用自定义验证器,验证纯数字,禁止输入小数、中文、字母、特殊符号。input的maxlength为最大输入多少位长度 效果图 <el-form ref"dataFormRef" :model"dataForm" :rules"dataRules" label-w…...

Android笔记(三十一):Deeplink失效问题
背景 通过deeplink启动应用之后,没关闭应用的情况下,再次使用deeplink会失效的问题,是系统bug导致的。此bug仅在某些设备(Nexus 5X)上重现,launchMode并且仅当应用程序最初通过深层链接启动并再次通过深层…...

图神经网络初步实验
实验复现来源 https://zhuanlan.zhihu.com/p/603486955 该文章主要解决问题: 1.加深对图神经网络数据集的理解 2.加深对图神经网络模型中喂数据中维度变化的理解 原理问题在另一篇文章分析: 介绍数据集:cora数据集 其中的主要内容表示为…...

创建线程时传递参数给线程
在C中,可以使用 std::thread 来创建和管理线程,同时可以通过几种方式将参数传递给线程函数。这些方法包括使用值传递、引用传递和指针传递。下面将对这些方法进行详细讲解并给出相应的代码示例。 1. 值传递参数 当你创建线程并希望传递参数时ÿ…...

兴业严选|美国总统都是不良资产出身 法拍市场是否将大众化
北京时间11月6日,特朗普赢得美国大选。 说起特朗普那就不得不提他的发家史,那可真是一笔笔不良资产投资堆出来的。 没错,特朗普就是处理不良资产的高手,战果丰硕。 改造斯威夫特小镇、 康莫德酒店、打造特朗普(TRUM…...

C#-拓展方法
概念:为现有的非静态变量类型,添加方法 语法: 访问修饰符 static 返回值 函数名(this 拓展类名 参数名, 参数类型 参数名,参数类型 参数名....){} 而public static void F(this Console()){ }是错的。Console是静态类不可以为静态类添加方…...

加锁失效,非锁之过,加之错也|京东零售供应链库存研发实践
本文导读 从事京东零售供应链库存业务,库存数量操作增减十分频繁,并且项目开发中会常常遇到各种并发情况,一旦库存数量操作有误,势必给前台销售产生损失影响,因此需要关注对库存数量并发操作下的一致性问题。 大部分…...

vue3 传值的几种方式
一.父组件传子组件 父组件 //父组件 <Decisionobject :Decisionselected"Decisionselected"></Decisionobject> <script lang"ts" setup> let Decisionselected ref(false); </script>子组件 <script lang"ts" s…...

AUTOSAR CP NVRAM Manager规范导读
一、NVRAM Manager功能概述 NVRAM Manager是AUTOSAR(AUTomotive Open System ARchitecture)框架中的一个模块,负责管理非易失性随机访问存储器(NVRAM)。它提供了一组服务和API,用于在汽车环境中存储、维护和恢复NV数据。以下是NVRAM Manager的一些关键功能: 数据存储和…...

2024阿里云CTF Web writeup
《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 前言 又是周末…...

软件著作权申请教程(超详细)(2024新版)软著申请
目录 一、注册账号与实名登记 二、材料准备 三、申请步骤 1.办理身份 2.软件申请信息 3.软件开发信息 4.软件功能与特点 5.填报完成 一、注册账号与实名登记 首先我们需要在官网里面注册一个账号,并且完成实名认证,一般是注册【个人】的身份。中…...

三维测量与建模笔记 - 3.2 直接线性变换法标定DLT
DLT - Direct Linear Transform 上图中,透视成像对应的公式是共线方程,可以参考以下链接: https://zhuanlan.zhihu.com/p/101549821https://zhuanlan.zhihu.com/p/101549821 对于标定来说,需要找到。已知量是。 (u,v)是…...

Whisper AI视频(音频)转文本
在信息化时代,如何高效处理丰富的音频和视频内容成为了一个重要课题。将这些内容转化为文本不仅能提高信息的可获取性,还能促进更广泛的传播。Whisper Desktop作为一款先进的语音识别工具,能够帮助用户轻松实现音频和视频的转文本功能。 什么…...

全网最详细RabbitMQ教学包括如何安装环境【RabbitMQ】RabbitMQ + Spring Boot集成零基础入门(基础篇)
目录 一、初始Rabbitmq1、什么是Rabbitmq,它的概述是什么?2、RabbitMQ的应用场景3、RabbitMQ主要组件4、RabbitMQ 的优点5、与其他消息队列性能比较 二、RabbitMQ环境安装初始化三、SpringAMQPRabbitMQ实战入门(基本API)1、实战入…...

esp32记录一次错误
报错信息 PS C:\XingNian\GeRen\4Gdownload\wireless-esp8266-dap> idf.py build Executing action: all (aliases: build) Running cmake in directory c:\xingnian\geren\4gdownload\wireless-esp8266-dap\build Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED1 …...

Moonshine - 新型开源ASR(语音识别)模型,体积小,速度快,比OpenAI Whisper快五倍 本地一键整合包下载
Moonshine 是由 Useful Sensors 公司推出的一系列「语音到文本(speech-to-text, STT)转换模型」,旨在为资源受限设备提供快速而准确的「自动语音识别(ASR)服务」。Moonshine 的设计特别适合于需要即时响应的应用场景&a…...

java-web-苍穹外卖-day1:软件开发步骤简化版+后端环境搭建
软件开发 感觉书本上和线上课程, 讲的太抽象, 不好理解, 但软件开发不就是为了开发应用程序吗?! 干嘛搞这么抽象,对吧, 下面个人对于软件开发的看法, 主打简单易懂, 当然,我一IT界小菜鸟, 对软件开发的认识也很浅显, 这个思维导图也仅仅是现阶段我的看法, 我以后会尽力…...

一个国产 API 开源项目,在 ProductHunt 杀疯了...
随着AI 大模型技术的兴起,全球产品更新和面市进程速度肉眼可见的加快,Product Hunt 作为全球知名的产品发现平台,每日都会精选出一系列产品能力强劲的新产品,这些产品不仅代表了技术前沿,还反映了市场的发展趋势。 上…...

斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)
斗破Qt目录: 斗破Qt编程入门系列之前言:认识Qt:Qt的获取与安装(四星斗师) 斗破QT编程入门系列之一:认识Qt:初步使用(四星斗师) 斗破QT编程入门系列之二:认识…...

木马病毒相关知识
1、 木马的定义 相当于一个远控程序(一个控制端[hack]、一个被控端[受害端]) 在计算机系统中,“特洛伊木马”指系统中被植入的、人为设计的程序,目的包括通过网终远程控制其他用户的计算机系统,窃取信息资料࿰…...

用 Python 写了一个天天酷跑(附源码)
Hello,大家好,给大家说一下,我要开始装逼了 这期写个天天酷跑玩一下叭! 制作一个完整的“天天酷跑”游戏涉及很多方面,包括图形渲染、物理引擎、用户输入处理、游戏逻辑等。由于Python是一种高级编程语言,…...

【网络-交换机】生成树协议、环路检测
路由优先级 路由优先级决定了在多种可达的路由类型中,哪种路由将被用来转发数据包。路由优先级值越低,对应路由的优先级越高,优先级值255表示对应的路由不可达。一般情况下,静态路由的优先级为1,OSPF路由优先级为110&a…...

C++ 中的 JSON 序列化和反序列化:结构体与枚举类型的处理
在 C 编程中,处理 JSON 数据是一项常见任务,特别是在需要与其他系统或前端进行数据交换时。nlohmann::json 库是一个功能强大且易于使用的 JSON 库,它允许我们轻松地在 C 中进行 JSON 数据的序列化和反序列化。本文将详细介绍如何使用 nlohma…...

MySQL 批量删除海量数据的几种方法
目录 一、问题分析 二、批量删除海量数据的几种方法 方法 1:使用 LIMIT 分批删除 方法 2:通过主键范围分批删除 方法 3:通过自定义批量删除存储过程 方法 4:创建临时表替换旧表 三、性能优化建议 总结 在数据库的日常维护…...

【docker入门】docker的安装
目录 Centos 7 添加docker 官方仓库到yum源 将 Docker 的官方镜像源替换为国内可以的 Docker 镜像源 安装docker 配置docker加速源 Ubuntu 创建 gpg key 目录 下载 gpg key 添加国内可用镜像源到 系统的 APT 仓库中 安装docker 配置加速源 Centos 7 添加docker 官方仓…...