JAVA-快速排序
目录
一、快速排序基本思想
二、快速排序的实现
1.Hoare法找基准值
2.挖坑法
3.前后指针法(了解)
三、快速排序的优化
1.三数取中法
2.递归到小的子区间时,可以考虑使用插入排序
四、非递归的写法
五、时间空间复杂度
一、快速排序基本思想
我们此次实现拿数组的第一个元素做为基准值![]()
right找到比tmp小的,left再找到比tmp大的就交换。如果交汇了就放入第一个元素,再把tmp放进来。 right必须先找left后找
把交汇处的下标给par,再分别从par两边重复之前的操作。而且这不就是二叉树吗。那么就适合用递归来处理了
二、快速排序的实现
public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end) {//当start >= end了证明只有一个元素,或者没有左右树了也就不需要排序了if(start >= end) {return;}//按照基准值对array数组的 [start,end]区间中的元素进行划分//并返回当前基准值下标int par = partitionHoare(array,start,end);//遍历左边quick(array,start,par-1);//遍历右边quick(array,par+1,end);}
1.Hoare法找基准值
从逻辑上已经构造好了,就差具体的操作了:
/*** Hoare法* @param array* @param left* @param right* @return*/private static int partitionHoare(int[] array, int left,int right) {//用来保存基准值下标int i = left;//记录基准值的值int tmp = array[left];//没交汇就继续循环while (left < right) {//left < right 必须写前面,防止6 7 8 9这种情况//找到最右边小于基准值的值while (left < right && array[right] >= tmp){right--;}//找到左边大于基准值的值while (left < right && array[left] <= tmp) {left++;}//交换swap(array,left,right);}//此时 left 和 right 交汇swap(array,i,left);//返回新的基准值下标return left;}//交换函数private static void swap(int[] array, int i, int j) {int tmp = array[i];array[i] = array[j];array[j] = tmp;}
测试代码:
public static void main(String[] args) {int[] array = {10,9,7,2,3,8,1};Sort.bubbleSort(array);System.out.println(Arrays.toString(array));}

出了刚才的Hoare法可以找基准值下面还有两种方法
2.挖坑法
先把基准值记录一下,再由right找到小于基准值的,然后left找到大于基准值的。两边来回填补。
最后tmp放入交汇处

细心的就会发现,这和Hoare法的数据顺序是不一样的。但也同样达到了效果
画图的时候里面有一些空,其实是保留了原来数据的,但是为了更好的理解就没有保留。但是在代码上原有的数据一定会被覆盖。
代码:
/*** 挖坑法* @param array* @param left* @param right* @return*/private static int partitionK(int[] array, int left,int right) {//记录第一个坑,做为基准值int tmp = array[left];while (left < right) {//找到最左边比基准值小的while (left < right && array[right] >= tmp) {right--;}//左边小的数据先放入,已经挖好了坑tmparray[left] = array[right];//找到最右边大于基准值的while (left < right && array[left] <= tmp) {left++;}//放入右边的新坑array[right] = array[left];}//left 和 right 交汇,填空array[left] = tmp;return left;}
这是最重要的一种方法,着重掌握
3.前后指针法(了解)
做选择题的时候可能会有。做题顺序: 挖坑法 > Hoare法 > 前后指针法
/*** 前后指针法 (做为了解)* @param array* @param left* @param right* @return*/private static int partitionPre(int[] array, int left, int right) {int prev = left ;int cur = left+1;while (cur <= right) {if(array[cur] < array[left] && array[++prev] != array[cur]) {swap(array,cur,prev);}cur++;}swap(array,prev,left);return prev;}
快速排序如果不做优化,数据量大了以后他是很有可能会栈溢出的。
但是计算做了优化也有可能会栈溢出,虽然快速排序是最快的,但耗费内存大也是他的缺点
三、快速排序的优化
1.三数取中法
快排在能取到中间值时,最快。

如果数组是一个有序的,那么就会开辟很多没必要的空间。浪费时间空间

那么三树取中就是:
用left 和 right 与 mid(数组中间下标的值) ,里面选居中的一个。做为基准值,并将他和left换一下

此时3做为基准值
那么最后基准值就在中间位置
写一个函数找到三个数之间中间的那个数的下标:
//返回的是中间值小标private static int midTreeNum(int[] array,int left,int right) {int mid = (left + right) / 2;if(array[left] < array[right]) {if(array[mid] < array[left]) {return left;}else if(array[right] < array[mid]) {return right;}else {return mid;}}else {if(array[mid] < array[right]) {return right;}else if(array[left] < array[mid]) {return left;}else {return mid;}}}
边看图边看代码,假设array[left] < array[right] 假设array[left] >= array[right]

public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end) {if(start >= end) {return;}//三数取中法int index = midTreeNum(array,start,end);swap(array,index,start);int par = partitionK(array,start,end);quick(array,start,par-1);quick(array,par+1,end);}
结果:

2.递归到小的子区间时,可以考虑使用插入排序
我们知道在趋于有序的时候插入排序最快,可以达到O(n)
public static void insertSortRange(int[] array,int left ,int right) {for (int i = left+1; i <= right; i++) {int tmp = array[i];int j = i-1;for (; j >= left; j--) {
// if(array[j] > tmp) { 不稳定的写法if(array[j] > tmp) {array[j+1] = array[j];}else {//防止第一次array[j]>tmp,从而j--到-1,执行不到这条语句
// array[j+1] = tmp;break;}}array[j+1] = tmp;}
}
public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end) {if(start >= end) {return;}//当分出来的,数组越小。递归的次数就越多了,但是趋于有序了就可以用插入排序if(end - start + 1 <= 10) {insertSortRange(array,start,end);return;}//三数取中法int index = midTreeNum(array,start,end);swap(array,index,start);int par = partitionK(array,start,end);quick(array,start,par-1);quick(array,par+1,end);}
四、非递归的写法
public static void quickSortNot(int[] array) {Stack<Integer> stack = new Stack<>();int left = 0;int right = array.length-1;int par = partitionK(array,left,right);if(par > left+1) {stack.push(left);stack.push(par-1);}if(par < right-1) {stack.push(par+1);stack.push(right);}while (!stack.isEmpty()) {right = stack.pop();left = stack.pop();par = partitionK(array,left,right);//保证左边至少有两个元素if(par > left+1) {stack.push(left);stack.push(par-1);}//保证右边至少有两个元素if(par < right-1) {stack.push(par+1);stack.push(right);}}
}
用栈来模拟,用栈后进先出的原理来模拟实现。
快速排序最好还是用递归来实现
五、时间空间复杂度
优化后的
时间复杂度:O(n*log2n)空间复杂度:O(log2n)稳定性:不稳定
相关文章:
JAVA-快速排序
目录 一、快速排序基本思想 二、快速排序的实现 1.Hoare法找基准值 2.挖坑法 3.前后指针法(了解) 三、快速排序的优化 1.三数取中法 2.递归到小的子区间时,可以考虑使用插入排序 四、非递归的写法 五、时间空间复杂度 一、快速排序基本思想 快速排序是 H…...
日志收集Day003
1.索引模板 查看所有索引模板 GET 10.0.0.101:9200/_template 2.查看单个索引模板 GET 10.0.0.101:9200/_template/.monitoring-es 3.创建索引模板 POST 10.0.0.101:9200/_template/lxctp {"aliases": {"DBA": {},"SRE": {},"K8S&qu…...
基于quartz,刷新定时器的cron表达式
文章目录 前言基于quartz,刷新定时器的cron表达式1. 先看一下测试效果2. 实现代码 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。 而且听说点赞的人每天的运气都不会太差&…...
数学大模型MAmmoTH:通过混合说明调整建立数学通才模型
向悦和陈文虎是该项目的主要作者。他们这个项目推出 MAmmoTH,这是一系列专为解决一般数学问题而定制的开源大型语言模型 (LLM)。 MAmmoTH 模型在 MathInstruct 上进行训练,MathInstruct 是我们精心策划的指令调整数据集。 MathInstruct 已编译 来自 13 个…...
Opencv学习
Long time no see!哈哈,假期终于有时间做一点自己喜欢的东西了 还是想说,每天花一点时间投在自己喜欢的事情上,或者专攻一些平时不学的方向,真的很酷! 图片绘制 对于图像绘制,可以分为:图像创…...
python生成图片和pdf,快速
1、下载安装 pip install imgkit pip install pdfkit2、wkhtmltopdf工具包,下载安装 下载地址:https://wkhtmltopdf.org/downloads.html 3、生成图片 import imgkit path_wkimg rD:\app\wkhtmltopdf\bin\wkhtmltoimage.exe # 工具路径,安…...
剑指Offer|LCR 044.在每个树行中找最大值
LCR 044.在每个树行中找最大值 给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。 示例 1: 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9] 解释:1/ \3 2/ \ \ 5 3 9 示例 2: 输入: root [1,2,3] 输出: [1,3] 解…...
PWM信号概述
什么是PWM信号? PWM(Pulse-width modulation)是脉冲宽度调制的缩写。 脉冲宽度调制是一种模拟信号电平数字编码方法。 脉冲宽度调制PWM是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式。所以根据面积等效法…...
关于BAR(PCIE BAR或AXI BAR)的解释
假设某BAR的默认值是xxxx_0000(这里表示8个比特位),其中低4位不可写,可操作的最低位是4,所以该BAR的大小是2^416字节; 1、系统软件向BAR写0xFF 2、系统软件读BAR,读到的值是0xF0,于是…...
计算机的错误计算(二百二十一)
摘要 利用一个数学解题器化简计算 实验表明,即使是数学解题器,也是一派胡言。 有一读者来信,询问数学大模型的推理事宜。现就前面的案例继续做一讨论。 例1. 化简计算摘要中算式。 下面是与一个数学解题器的对话。 点评: &am…...
【力扣Hot 100】矩阵1
矩阵置零:1. 开两个数组判断该行/该列是否有0;2. 用第0行/第0列分别判断该列/该行是否有0 螺旋矩阵:记录方向,一直按某方向前进,遇到障碍方向就变一下 1. 矩阵置零 给定一个 *m* x *n* 的矩阵,如果一个元…...
移动端VR处理器和传统显卡的不同
骁龙 XR 系列芯片 更多地依赖 AI 技术 来优化渲染过程,而传统的 GPU 渲染 则倾向于在低画质下运行以减少负载。这种设计是为了在有限的硬件资源下(如移动端 XR 设备)实现高性能和低功耗的平衡。以下是具体的分析: 1. AI 驱动的渲染…...
「 机器人 」利用数据驱动模型替代仿真器:加速策略训练并降低硬件依赖
前言 在强化学习(Reinforcement Learning, RL)中,策略训练需要大量的交互数据(状态、动作、奖励、下一状态),而这些数据通常来自仿真器或真实硬件。传统高保真仿真器虽然能在一定程度上模拟飞行器的动力学,但往往计算量大、开发成本高,且仍可能与真实环境存在差距。为此…...
MATLAB 如何避免复杂shp文件对inpolygon的影响
**任务描述:**当我想用inpolygon函数将属于非洲的pixel选出来时,发现因为周边小岛的影响,pixel选取有问题,如下图。 第一种解决办法: 首先将复杂shp文件查分成简单的shp文件,即将不相交的元素分离开 [QGIS…...
【2024年华为OD机试】 (C卷,200分)- 贪吃的猴子(JavaScriptJava PythonC/C++)
一、问题描述 题目解析 问题描述 一只猴子来到果园,发现许多串香蕉排成一行,每串香蕉上有若干根香蕉。每串香蕉的根数由数组 numbers 给出。猴子每次只能从行的开头或末尾获取香蕉,并且只能获取 N 次。求猴子最多能获取多少根香蕉。 输入…...
PostgreSQL中级专家是什么意思?
数据库技术领域,PostgreSQL 作为一种广泛使用的开源关系型数据库管理系统,吸引了众多技术人员深入学习和研究。“PostgreSQL 中级专家” 是对掌握该数据库特定技能层次的一种描述。 知识储备 中级专家深入理解 PostgreSQL 的体系结构,包括进程…...
从根源分析,调试,定位和解决MacOS ld: unsupported tapi file type ‘!tapi-tbd‘ in YAML file
你要是遇到同样错误,找一圈都没有解决,建议认真读一下本文,这个应该是最终极的解决办法,从原理上剖析了产生的原因,同时给出来了调试和定位的办法。 maccos使用brew安装了一个gcc14, 结果编译一个最简单的程序都报错&a…...
【Uniapp-Vue3】previewImage图片预览
如果我们想要实现点击一张图片放大,并能够左右滑动,就要使用previewImage这个API。 uni.previewImage({ current:xxx, // 当前图片下标 urls:xxx, // 图片路径组 // 其他参数 }) 我们先编写一个点击图片的事件,并传递当前点击图片的下标&…...
doris:Insert Into Values
INSERT INTO VALUES 语句支持将 SQL 中的值导入到 Doris 的表中。INSERT INTO VALUES 是一个同步导入方式,执行导入后返回导入结果。可以通过请求的返回判断导入是否成功。INSERT INTO VALUES 可以保证导入任务的原子性,要么全部导入成功,要么…...
15 分布式锁和分布式session
在java中一个进程里面使用synchronized在new出来对象头信息中加锁,如果是静态方法中在加载的类信息中加锁(我们在锁的原理中讲过)。如果使用lock加锁可以自己指定。这些都是在同一个进程空间中的操作。如果在分布式环境中由于程序不在一个进程空间,就没办…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...


