双路快速排序和三路排序算法
双路快速排序
一、概念及其介绍
双路快速排序算法是随机化快速排序的改进版本,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 …...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
