数据结构-8.Java. 七大排序算法(下篇)

本篇博客给大家带来的是排序的知识点, 由于时间有限, 分两天来写, 下篇主要实现最后一种排序算法: 归并排序。同时把中篇剩下的快排非递归实现补上.
文章专栏: Java-数据结构
若有问题 评论区见
欢迎大家点赞 评论 收藏 分享
如果你不知道分享给谁,那就分享给薯条.
你们的支持是我不断创作的动力 .
王子,公主请阅!!!
1. 快速排序的非递归实现
拿到第一个基准值pivot之后, 如何进行左右子序列的快速排序呢?
可以利用栈保存左区间 和 右区间.
1.1 具体实现
1. 利用上篇文章的 partition算法拿到第一个基准值,用栈存储左区间 和 右区间,
2. 重复第一步,直到栈为空.
1.1.1 区间入栈细节
如下分析图:

1.2 代码如下:
//挖坑法,求基准值.
private static int partition2(int[] array,int left,int right) {int key = array[left];while(left < right) {while(left < right && array[right] >= key) {right--;}//从右边开始第一个比key小的元素覆盖[left]array[left] = array[right];while(left < right && array[left] <= key) {left++;}//从左边开始第一个比key大的元素覆盖空位.array[right] = array[left];}//key填补最终的空位,此时left=rightarray[left] = key;return left;}
//快速排序法的非递归实现.public static void quickSortNor(int[] array) {Stack<Integer> stack = new Stack<>();int left = 0;int right = array.length-1;//拿到第一个基准int pivot = partition2(array,left,right);//左序列区间端点入栈.if(pivot-1 > left) {stack.push(left);stack.push(pivot-1);}//右序列区间端点入栈.if (pivot+1 < right) {stack.push(pivot+1);stack.push(right);}while(!stack.isEmpty()) {right = stack.pop();left = stack.pop();pivot = partition2(array,left,right);if(pivot-1 > left) {stack.push(left);stack.push(pivot-1);}if (pivot+1 < right) {stack.push(pivot+1);stack.push(right);}}}
1.3 快速排序的特性总结:
1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(logN)
4. 稳定性:不稳定
2. 归并排序
2.1 归并排序的基本思想
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and
Conquer)的一个非常典型的应用。原序列分解成若干个子序列, 子序列排序, 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
2.2 具体步骤
2.2.1 分解操作
定义left = 0, right = array.length-1; mid = (left + right)/2; 递归分解即可.[left,mid],[mid+1,right]; 注意递归的终止条件 left >= right.
/*** 归并排序* 时间复杂度: O(N*logN) 和快速排序类似,** 空间复杂度:O(N) - 临时数组和原数组长度一样.** 稳定性: 稳定.** @param array*/
public static void mergeSort(int[] array) {mergeSortFunc(array,0,array.length-1);}//先分解,再归并排序.private static void mergeSortFunc(int[] array,int left,int right) {if(left >= right) return;int mid = (left+right)/2;//分解左右mergeSortFunc(array,left,mid);mergeSortFunc(array,mid+1,right);//将小数组排序合并merge(array,left,mid,right);}

2.2.1 合并排序操作

1. 定义一个临时数组,用来存放有序的子序列,长度为 right - left + 1, k 指向数组起始位置; 令s1指向[left],s2指向[mid+1].
2. [s1] 与 [s2] 比较, 若[s1] > [s2], 则 [s2] 放到数组中, s2++, [s2] < [s1]…类推
3. 重复第二步 直到 s1 > mid && s2 > right.
4. s1 与 s2 中两边的元素总有一边先放完, 把剩下的那边元素放入临时数组即可.

5. 最后一步将有序的临时数组放回原数组.
//归并排序的核心private static void merge(int[] array,int left,int mid,int right) {int s1 = left;int s2 = mid+1;int k = 0;int[] tmpArr = new int[right-left+1];while(s1 <= mid && s2 <= right) {if(array[s2] <= array[s1]) { //等号不取便稳定.tmpArr[k++] = array[s2++];}else {tmpArr[k++] = array[s1++];}}//s1中所有元素都大于s2,s2放完了,s1还没放完.while(s1 <= mid) {tmpArr[k++] = array[s1++];}//s2中所有元素都大于s1,s1放完了,s2还没放完.while(s2 <= right) {tmpArr[k++] = array[s2++];}//tmpArr为有序数组.for (int i = 0; i < tmpArr.length; i++) {array[i+left] = tmpArr[i];//left不一定为0.}}
2.3 归并排序的非递归实现
在归并排序核心算法的基础上, 定义变量gap = 1, 循环for (int i = 0; i < array.length; i += gap*2)中, left = i; mid = left+gap-1; right = mid+gap; 这么定义可以将原数组分为若干个长度为2的小数组.
由于要不断分解, 故gap应当写一个循环.

处理细节:
当gap > array.length/2时, mid和right可能会越界, 所以 需要加上条件,防止越界.
代码如下:
//归并排序的核心private static void merge(int[] array,int left,int mid,int right) {int s1 = left;int s2 = mid+1;int k = 0;int[] tmpArr = new int[right-left+1];while(s1 <= mid && s2 <= right) {if(array[s2] <= array[s1]) { //等号不取便稳定.tmpArr[k++] = array[s2++];}else {tmpArr[k++] = array[s1++];}}//s1中所有元素都大于s2,s2放完了,s1还没放完.while(s1 <= mid) {tmpArr[k++] = array[s1++];}//s2中所有元素都大于s1,s1放完了,s2还没放完.while(s2 <= right) {tmpArr[k++] = array[s2++];}//tmpArr为有序数组.for (int i = 0; i < tmpArr.length; i++) {array[i+left] = tmpArr[i];//left不一定为0.}}//归并排序的非递归实现.public static void mergeSortNor(int[] array) {int gap = 1;while(gap < array.length) {for (int i = 0; i < array.length; i += gap*2) {int left = i;int mid = left+gap-1;int right = mid+gap;//mid和right可能会越界if(mid >= array.length) {mid = array.length-1;}if(right >= array.length) {right = array.length-1;}merge(array,left,mid,right);}gap *= 2;}}
2.4 归并排序的特性总结:
1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN) -> 算法与快排类似.
3. 空间复杂度:O(N) -> 临时数组长度与原数组相同.
4. 稳定性:稳定
总的来说, 快排和归并排序还是需要花时间去想清楚每一步是怎么回事, 代码为什么要这么写??? 去解答心里有十万个为什么, 解答出自己问自己的所有的问题, 就说明掌握了这个知识点.
本篇博客到这里就结束啦, 感谢观看, 期待与你的下一次相遇!!!
相关文章:
数据结构-8.Java. 七大排序算法(下篇)
本篇博客给大家带来的是排序的知识点, 由于时间有限, 分两天来写, 下篇主要实现最后一种排序算法: 归并排序。同时把中篇剩下的快排非递归实现补上. 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是…...
缓存穿透、缓存击穿、缓存雪崩的区别与解决方案
1. 缓存穿透(Cache Penetration) 定义:大量请求查询 数据库中不存在的数据,导致请求绕过缓存直接访问数据库,造成数据库压力过大。 场景: 恶意攻击:例如用不存在的用户ID频繁请求。 业务误操作…...
DeepSeek私有化部署+JAVA通过API调用离线大模型问答
在当今快速发展的数字化时代,企业对于高效、灵活的技术解决方案需求日益增长。DeepSeek作为一款领先的智能搜索与分析平台,凭借其强大的数据处理能力和精准的搜索结果,已经成为众多企业提升运营效率的得力助手。为了更好地满足企业对数据安全…...
【go语言规范】Gopherfest 2015 | Go Proverbs with Rob Pike的 总结
根据 Gopherfest 2015 | Go Proverbs with Rob Pike 的演讲,总结内容如下: 虽然已是十年前的产物,但是proverbs的价值依旧存在 以下是整合补充内容后的完整总结,涵盖 Rob Pike 在 Gopherfest 2015 演讲 “Go Proverbs” 中的核心…...
【吾爱出品】针对红警之类老游戏适用WIN10和11的补丁cnc-ddraw7.1汉化版
针对红警之类老游戏适用WIN10和11的补丁cnc-ddraw7.1汉化版 链接:https://pan.xunlei.com/s/VOJ8PZd4avMubnDzHQAeZDxWA1?pwdnjwm# 直接复制到游戏安装目录,保持与游戏主程序同目录下。...
内容中台驱动企业数字化内容管理高效协同架构
内容概要 在数字化转型加速的背景下,企业对内容管理的需求从单一存储向全链路协同演进。内容中台作为核心支撑架构,通过统一的内容资源池与智能化管理工具,重塑了内容生产、存储、分发及迭代的流程。其核心价值在于打破部门壁垒,…...
【第14章:神经符号集成与可解释AI—14.4 神经符号集成与可解释AI的未来发展趋势与挑战】
想象一下,如果AI既能像人类一样直觉感知(比如一眼认出街角的咖啡店),又能像数学家一样逻辑推理(比如计算最优路线避开拥堵),这个世界会变成什么样?这种“双脑协同”正是神经符号集成技术的终极目标。 但现实是,当前99%的AI系统要么只会“死记硬背”数据(如深度学习模…...
[JVM篇]虚拟机性能监控、故障处理工具
虚拟机性能监控、故障处理工具 基础故障处理工具 jps(JVM Peocess Status Tool - 虚拟机进程状况工具) jstat(JVM Statistics Monitoring Too - 虚拟机统计信息监视工具) jinfo( Configuration info for Java - Java配置信息工具) jmap(Memory Map for…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_cycle_t 类型
ngx_cycle_t 定义在 src/core/ngx_core.h typedef struct ngx_cycle_s ngx_cycle_t; ngx_cycle_s 定义在 src/core/ngx_cycle.h struct ngx_cycle_s {void ****conf_ctx;ngx_pool_t *pool;ngx_log_t *log;ngx_log_t …...
WHERE子句中的条件
在SQL查询中,WHERE子句用于指定筛选条件,以限制从数据库表中检索出的数据行。WHERE子句通常位于SELECT、UPDATE、DELETE等SQL语句中,紧跟在FROM子句(对于SELECT语句)或其他相关子句之后。 一、WHERE子句的基本语法 sq…...
Effective Objective-C 2.0 读书笔记——内存管理(下)
Effective Objective-C 2.0 读书笔记——内存管理(下) 在 dealloc 方法中只释放引用并解除监听 对象在经历其生命期后 ,最终会为系统所回收 ,这时就要执行dealloc 方法了。 在每个对象的生命期内,此方法仅执行一次&a…...
[Spring Boot] Expense API 实现
[Spring Boot] Expense API 实现 项目地址:expense-api 项目简介 最近跟着视频做的一个 spring boot 的项目,包含了比较简单的记账功能的实现(只限 API 部分),具体实现的功能有: 记账(expen…...
Pell数列【一本通在线评测】
目录 描述 输入描述 输出描述 用例输入 1 用例输出 1 什么是pell数列 一、定义与递推关系 二、数学性质 三、应用领域 四、编程实现要点 五、扩展与相关概念 C代码实现 描述 Pell数列a1,a2,a3,...的定义是这样的,a11,a22,...,an2an−1a…...
linux ollama deepseek等大语言模型的model文件的存储目录
linux ollama deepseek等大语言模型的model文件的存储目录 一、用ollama serve启动的,模型数据存放在: /usr/share/ollama/.ollama/models二、如果在自启动文件中指定了工作目录,则在工作目录下的.ollama/models 1.自启动服务 /etc/system…...
【PyQt】工具栏(QToolBar)与动作按钮(QAction)使用指南
PyQt工具栏(QToolBar)与动作按钮(QAction)使用指南 🛠️ 一、基础用法示例 🌟 class MainWindow(QMainWindow):def __init__(self):super().__init__()# 创建工具栏 🔧self.toolbar self.addToolBar("主工具栏")# 创建动作集合 …...
软路由折腾 | OpenWrt安装后基础配置指南:联网设置与DNS优化
在PVE中安装OpenWrt教程 一、网络基础配置 1. 确认网络接口角色 OpenWrt旁路由通常仅需配置LAN口,无需WAN口。其流量通过主路由转发,因此需确保: 物理连接:OpenWrt的LAN口(如eth0)桥接到主路由的局域网&…...
设置默认构建变体 Build Variant
Android Studio在打开项目时有时会把我设置好的build Variant改为默认的变体,没注意的话可能打完包才发现打错了,浪费时间。因此,有必要通过代码设置一个我想要的默认变体。 代码其实很简单,只要在变体下面加上isDefault true即可…...
【大模型】DeepSeek使用与原理解析:从V3到R1
文章目录 一、引言二、使用与测评1.7大R1使用技巧2.官网实测 发展历程三、Deepseek MoE:专家负载均衡 (2024年1月)四、GRPO:群体相对策略优化(DeepSeek-Math,2024年4月)五、三代注意力ÿ…...
DAY04 Object、Date类、DateFormat类、Calendar类、Math类、System类
学习目标 能够说出Object类的特点是所有类的祖宗类,任意的一个类都直接或者间接的继承了Object类,都可以使用Object类中的方法Animal extends Object:直接继承Cat extends Animal:间接继承 能够重写Object类的toString方法altinsert,选择toString 能够重写Object类的equals方法…...
oracle 19c安装DBRU补丁时报错CheckSystemSpace的处理
oracle 19c的补丁目前已经发布到19.26版本了,数据库补丁安装也是数据库运维中的一个常见工作;近期在一个安装补丁的环境遇到了Prerequisite check "CheckSystemSpace" failed.错误,看起来是磁盘剩余空间不足的告警;按以…...
图像生成GAN和风格迁移
文章目录 摘要abstract1.生成对抗网络 GAN1.1 算法步骤 2.风格迁移2.1 损失函数2.2 论文阅读2.2.1 简介2.2.2 方法2.2.3 实验2.2.4 结论 3.总结 摘要 本周学习了生成对抗网络(GAN)与风格迁移技术在图像生成中的应用。首先介绍了GAN模型中生成器与判别器…...
golangAPI调用deepseek
目录 1.deepseek官方API调用文档1.访问格式2.curl组装 2.go代码1. config 配置2.模型相关3.错误处理4.deepseekAPI接口实现5. 调用使用 3.响应实例 1.deepseek官方API调用文档 1.访问格式 现在我们来解析这个curl 2.curl组装 // 这是请求头要加的参数-H "Content-Type:…...
【第15章:量子深度学习与未来趋势—15.3 量子深度学习在图像处理、自然语言处理等领域的应用潜力分析】
一、开篇:为什么我们需要关注这场"量子+AI"的世纪联姻? 各位技术爱好者们,今天我们要聊的这个话题,可能是未来十年最值得押注的技术革命——量子深度学习。这不是简单的"1+1=2"的物理叠加,而是一场可能彻底改写AI发展轨迹的范式转移。 想象这样一个…...
JAVA安全—Shiro反序列化DNS利用链CC利用链AES动态调试
前言 讲了FastJson反序列化的原理和利用链,今天讲一下Shiro的反序列化利用,这个也是目前比较热门的。 原生态反序列化 我们先来复习一下原生态的反序列化,之前也是讲过的,打开我们写过的serialization_demo。代码也很简单&…...
LangChain大模型应用开发:提示词工程应用与实践
介绍 大家好,博主又来给大家分享知识了。今天给大家分享的内容是LangChain提示词工程应用与实践。 在如今火热的大语言模型应用领域里,LangChain可是一个相当强大且实用的工具。而其中的提示词(Prompt),更是我们与语言模型进行有效沟通的关…...
【数据结构入门 65 题】目录
目录 1 函数题2 编程题3 数据结构实现 1 函数题 6-1 单链表逆转 6-2~6-6 线性表基本操作 6-7 在一个数组中实现两个堆栈 6-8 求二叉树高度 6-9 二叉树的遍历 6-10 二分查找 6-11 先序输出叶结点 6-12 二叉搜索树的操作集 2 编程题 3 数据结构实现 栈和队列...
osgearth控件显示中文(八)
当前自己知道的方法大概有以下两种: (一)直接转成utf8 其实在前面的文章中已经有了。 osgEarth::Annotation::PlaceNode *pn = new osgEarth::Annotation::PlaceNode(GeoPoint(geoSRS, 110, 34), String2UTF8("中国"), style);std::wstring String2Wstring(con…...
2025 N1CTF crypto 复现
近一个月都没有学习了,一些比赛也没有打,很惭愧自己还是处在刚放假时的水平啊,马上开学了,抓紧做一些训练来康复。 CheckIn import os from Crypto.Util.number import * from secret import FLAGp, q getPrime(512), getPrime…...
Windows Defender Control--禁用Windows安全中心
Windows Defender Control--禁用Windows安全中心 链接:https://pan.xunlei.com/s/VOJDuy2ZEqswU4sEgf12JthZA1?pwdtre6#...
mount 出现 2038 问题
在 linux 上挂载 ext4 文件系统时出现了 2038 年问题,如下: [ 236.388500] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null) [ 236.388560] ext4 filesystem being mounted at /root/tmp supports timestamps until 2…...
