快速排序算法的递归和非递归

基本思路

选择一个基准值,将数组划分三个区域,小于基准值的区域位于左侧,等于基准值的区域位于中间,大于基准值的区域位于右侧。将大于和小于区域继续进行分区,周而复始,不断进行分区和交换,直到排序完成

递归

思路:

步骤1:

在当前分区范围[l,r]中随机选中一个数作为基准值,交换到分区范围的最右侧,即r位置

步骤2:

以r位置基准值进行分区

步骤3:

对所以小于区域和大于区域继续进行步骤1操作,直到范围为1结束

单次分区过程:

less 代表小于基准值分区范围,more代表大于分区值范围,index代表当前待比较位置,r为当前分区范围最右位置

比较当前index位置和基准位置

如果 arr[index] == arr[r] ,则index向右移动

如果大于,则 more向左移动,并将index位置的数与more位置的数进行交换

如果小于,则将 less右侧位置的数与index数交换;即less范围扩大 less++,交换less和index位置数,index右移

code:
    //递归public static void quickSortRecursive(int [] arr){if(arr == null || arr.length < 2)return;progress(arr,0,arr.length-1);}//让arr在[l,r]上有序public static void progress(int [] arr,int l,int r){if(l >= r){return;}//swap(arr, L + (int) (Math.random() * (R - L + 1)), R);//指定一个[l,r]范围随机位置放到最右侧作为基准值// math.random: [0,1)// math.random * x : [0,x)// Math.random() * (r -l + 1) : l到r长度范围内的一个随机数, + l则定位到数组的索引上swap(arr,l + (int)(Math.random() * (r -l + 1)),r);int [] equalArea = partition(arr,l,r);progress(arr,l,equalArea[0] -1);progress(arr,equalArea[1] + 1,r);}
//让arr以r位置数为基准,<arr[r]位置的数放左边,>arr[r]位置的数放右边 ==arr[r]位置的数位于中间//返回==arr[r]位置的数最左和最右位置public static int[] partition(int [] arr,int l,int r){//如果l > r,则数组不合规,返回一个无效值索引if(l > r) return new int[] { -1, -1 };//如果l == r,则说明只有一个值,那么等于分区也就是当前一个位置的索引if(l == r) return new int[] {l,r};//l < r//基准位置 r//less代表 <分区 的最右一个位置索引int less = l -1;//more代表 >分区 的最左一个位置的索引int more = r;//index代表待分区数最左位置索引int index = l;//进行分区,越界条件是待分区索引来到以分区区域[大于分区]while (index < more){//System.out.println("less,index,more:"+less+","+index + ","+more);//如果待分区数 == 基准值,那么说明该数不是大于分区的数,index向右移动if(arr[index] == arr[r]){index++;}//如果待分区数 < 基准值,那么说明该位置数是属于小于分区的数,则将该数交换到小于分区去if(arr[index] < arr[r]){//小于分区范围扩大less++;//将当前位置交换到小于分区//此时当前位置是等于或者小于分区的数swap(arr,index,less);//索引index需要向右移动index++;//等价于//swap(arr,index++,++less);}//如果待分区数 > 基准值,那么说明该位置数是属于大于分区的数,则将该数交换到大于分区去//此时index不移动,因为将位置的数交换到index位置上了if(arr[index] > arr[r]){//大于范围向左扩张more--;//当前数交换到大于区域中,交换来的数是一个未知大小的数,所以index不移动swap(arr,index,more);//等价于//swap(arr,index,--more);}}//遍历完成后,此时r位置为等于区域的数,需要交换到等于分区中swap(arr,more,r);//交换完成后,less为小于分区最右索引,more为等于分区最右索引//more原本为大于分区最左位置索引,但是将r交换到该位置后,大于分区向右缩减了一个位置,此时more位置为等于分区最右索引return new int[]{less+1,more};}public static void swap(int [] arr,int l,int r){int temp = arr[l];arr[l] = arr[r];arr[r] = temp;}

非递归

思路与递归一致,仅是将系统栈替换为自己控制的栈

使用栈记录每次分区得到的左右位置

然后出栈顶元素,继续分区,将新的分区如栈,直到栈为空

使用一个辅助对象用于入栈时保存分区位置 op

code:
    //非递归版//使用栈记录每次分区得到的左右位置//然后出栈顶元素,继续分区,将新的分区如栈,直到栈为空//使用一个辅助对象用于入栈时保存分区位置 oppublic static void quickSortUnRecursive(int [] arr){if(arr == null || arr.length < 2) return;int N = arr.length;Stack<Op> stack = new Stack<>();//随机得到基准值,放到最右位置swap(arr, (int)(Math.random() * N),N-1);//分区int [] equalArea = partition(arr,0,N-1);//将分区后的范围入栈stack.push(new Op(0,equalArea[0] -1));stack.push(new Op(equalArea[1]+1,N-1));//临时变量,保存出栈的范围值Op temp = new Op(0,0);while (!stack.isEmpty()){//出栈temp = stack.pop();//继续对当前范围进行分区//如果分区得到的范围错误,说明该区域已经排好序了if(temp.l >= temp.r)continue;//随机基准值swap(arr,temp.l + (int) (Math.random() * (temp.r - temp.l + 1)), temp.r);//分区equalArea = partition(arr,temp.l, temp.r);//入栈stack.push(new Op(temp.l, equalArea[0] -1));stack.push(new Op(equalArea[1]+ 1, temp.r));}}public static class Op{public int l;public int r;public Op(int l,int r){this.l = l;this.r = r;}}//让arr以r位置数为基准,<arr[r]位置的数放左边,>arr[r]位置的数放右边 ==arr[r]位置的数位于中间//返回==arr[r]位置的数最左和最右位置public static int[] partition(int [] arr,int l,int r){//如果l > r,则数组不合规,返回一个无效值索引if(l > r) return new int[] { -1, -1 };//如果l == r,则说明只有一个值,那么等于分区也就是当前一个位置的索引if(l == r) return new int[] {l,r};//l < r//基准位置 r//less代表 <分区 的最右一个位置索引int less = l -1;//more代表 >分区 的最左一个位置的索引int more = r;//index代表待分区数最左位置索引int index = l;//进行分区,越界条件是待分区索引来到以分区区域[大于分区]while (index < more){//System.out.println("less,index,more:"+less+","+index + ","+more);//如果待分区数 == 基准值,那么说明该数不是大于分区的数,index向右移动if(arr[index] == arr[r]){index++;}//如果待分区数 < 基准值,那么说明该位置数是属于小于分区的数,则将该数交换到小于分区去if(arr[index] < arr[r]){//小于分区范围扩大less++;//将当前位置交换到小于分区//此时当前位置是等于或者小于分区的数swap(arr,index,less);//索引index需要向右移动index++;//等价于//swap(arr,index++,++less);}//如果待分区数 > 基准值,那么说明该位置数是属于大于分区的数,则将该数交换到大于分区去//此时index不移动,因为将位置的数交换到index位置上了if(arr[index] > arr[r]){//大于范围向左扩张more--;//当前数交换到大于区域中,交换来的数是一个未知大小的数,所以index不移动swap(arr,index,more);//等价于//swap(arr,index,--more);}}//遍历完成后,此时r位置为等于区域的数,需要交换到等于分区中swap(arr,more,r);//交换完成后,less为小于分区最右索引,more为等于分区最右索引//more原本为大于分区最左位置索引,但是将r交换到该位置后,大于分区向右缩减了一个位置,此时more位置为等于分区最右索引return new int[]{less+1,more};}public static void swap(int [] arr,int l,int r){int temp = arr[l];arr[l] = arr[r];arr[r] = temp;}

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

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

相关文章

超详细的 pytest 教程(一)使用入门篇

前言 pytest到目前为止还没有翻译的比较好全面的使用文档&#xff0c;很多英文不太好的小伙伴&#xff0c;在学习时看英文文档还是很吃力。本来去年就计划写pytest详细的使用文档的&#xff0c;由于时间关系一直搁置&#xff0c;直到今天才开始写。本文是第一篇&#xff0c;主…

【JAVA】Object类与抽象类

作者主页&#xff1a;paper jie_的博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和…

Vue--1.4Vue指令

Vue会根据不同的指令&#xff0c;针对标签实现不同的功能。 指令&#xff1a;带有v-前缀的特殊标签属性 v-前缀"表达式" 1.v-html 作用:动态解析标签innerHTML <!doctype html> <html> <head><meta charset"utf-8"><meta …

计算机竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改

目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…

软件测试/测试开发丨ChatGPT:带你进入智能对话的新时代

简介 人工智能时代来临 我们正处于AI的iPhone时刻。——黄仁勋&#xff08;英伟达CEO&#xff09; ChatGPT 好得有点可怕了&#xff0c;我们距离危险的强人工智能不远了。——马斯克&#xff08;Tesla/SpaceX/Twitter CEO&#xff09; 以上的内容说明我们现在正处于一个技术大…

【uni-app】

准备工作 1.下载hbuilder&#xff0c;插件使用Vue3的uni-app项目 2.需要安装编译器 3.下载微信开发者工具 4.点击运行->微信开发者工具 5.打开微信开发者工具的服务端口 效果图 page.json&#xff08;添加路由&#xff0c;修改底层导航栏&#xff0c;背景色&#xff09…

读书笔记:多Transformer的双向编码器表示法(Bert)-1

多Transformer的双向编码器表示法 Bidirectional Encoder Representations from Transformers&#xff0c;即Bert&#xff1b; 本笔记主要是对谷歌Bert架构的入门学习&#xff1a; 介绍Transformer架构&#xff0c;理解编码器和解码器的工作原理&#xff1b;掌握Bert模型架构…

2023.9.7 关于 TCP / IP 的基本认知

目录 网络协议分层 TCP/IP 五层&#xff08;四层&#xff09;模型 应用层 传输层 网络层&#xff08;互联网层&#xff09; 数据链路层&#xff08;网络接口层&#xff09; 物理层 网络数据传输的基本流程 网络协议分层 为什么需要分层&#xff1f; 分层之后&#xff0c…

MATLAB实现数据插值

目录 一.理论知识 二.一维插值实例 三.二维插值实例 一.理论知识 所谓插值&#xff0c;顾名思义&#xff0c;插入数值。很多时候&#xff0c;我们仅有离散点上的数据&#xff0c;这时如果我们想要分析变量之间的函数关系&#xff0c;则无法实现。但如果通过插值处理&#xf…

PCL入门(四):kdtree简单介绍和使用

目录 1. kd树的意义2. kd树的使用 参考博客《欧式聚类&#xff08;KD-Tree&#xff09;详解&#xff0c;保姆级教程》和《(三分钟)学会kd-tree 激光SLAM点云搜索常见》 1. kd树的意义 kd树是什么&#xff1f; kd树是一种空间划分的数据结构&#xff0c;对于多个维度的数据&a…

电商(淘宝1688京东拼多多等)API接口服务:提升商业效率和用户体验的关键

电商API接口服务&#xff1a;提升商业效率和用户体验的关键 随着电子商务的飞速发展&#xff0c;电商企业需要不断提升自身的业务能力和服务质量&#xff0c;以应对日益激烈的市场竞争。为了更好地满足商家和消费者的需求&#xff0c;电商API接口服务应运而生。本文将探讨电商…

计算机毕设 大数据商城人流数据分析与可视化 - python 大数据分析

文章目录 0 前言课题背景分析方法与过程初步分析&#xff1a;总体流程&#xff1a;1.数据探索分析2.数据预处理3.构建模型 总结 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到…

jmeter调试错误大全

一、前言 在使用jmeter做接口测试的过程中大家是不是经常会遇到很多问题&#xff0c;但是无从下手&#xff0c;不知道从哪里开始找起&#xff0c;对于初学者而言这是一个非常头痛的事情。这里结合笔者的经验&#xff0c;总结出以下方法。 二、通过查看运行日志调试问题 写好…

【常用代码14】el-input输入框内判断正则,只能输入数字,过滤汉字+字母。

问题描述&#xff1a; el-input输入框&#xff0c;只能输入数字&#xff0c;但是不能显示输入框最右边的上下箭头&#xff0c; <el-input v-model"input" type"number" placeholder"请输入内容" style"width: 200px;margin: 50px 0;&…

两种解法解决LCR 008. 长度最小的子数组【C++】

文章目录 [LCR 008. 长度最小的子数组](https://leetcode.cn/problems/2VG8Kg/description/)解法暴力解法滑动窗口&#xff08;双指针法&#xff09; LCR 008. 长度最小的子数组 解法 暴力解法 //暴力解法&#xff1a; //使用双for循环依次遍历数组&#xff0c;罗列出所有情况…

华为云 异构数据迁移

数据库和应用迁移 UGO&#xff08;Database and Application Migration UGO&#xff0c;以下简称为UGO&#xff09;是专注于异构数据库结构迁移的专业服务。可将源数据库中的DDL、DML和DCL一键自动转换为华为云GaussDB/RDS的SQL语法&#xff0c;通过数据库评估、对象迁移两大核…

计算机竞赛 基于深度学习的植物识别算法 - cnn opencv python

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 MobileNetV2网络4 损失函数softmax 交叉熵4.1 softmax函数4.2 交叉熵损失函数 5 优化器SGD6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的植物识别算法 ** …

Vue3,Typescript中引用组件路径无法找到模块报错

是这么个事&#xff0c;我在vue3新创建的项目里&#xff0c;写了个组件叫headerIndex.vue&#xff0c;放到app.vue中import就会报错 路径肯定没写错&#xff0c;找到了解决方法&#xff0c;但是也没想明白为什么 解决方法如下 在vite-env.d.ts文件中加入 declare module &qu…

AJAX学习笔记6 JQuery对AJAX进行封装

AJAX学习笔记5同步与异步理解_biubiubiu0706的博客-CSDN博客 AJAX请求相关的代码都是类似的&#xff0c;有很多重复的代码&#xff0c;这些重复的代码能不能不写&#xff0c;能不能封装一个工具类。要发送ajax请求的话&#xff0c;就直接调用这个工具类中的相关函数即可。 用J…