当前位置: 首页 > news >正文

归并排序 Java 实现(递归 + 非递归)

目录

1. 递归版归并排序(最常用)

2. 非递归版归并排序(迭代实现)

核心说明

总结


归并排序是分治思想的经典实现,核心是:拆分数组→合并有序子数组。 时间复杂度:O(n log n),空间复杂度:O(n),稳定排序。

下面直接给你可直接运行的 Java 代码,包含递归版非递归(迭代)版


1. 递归版归并排序(最常用)

思路:

  1. 把数组从中间拆分成左右两部分
  2. 递归排序左右子数组
  3. 合并两个有序子数组为一个有序数组
public class MergeSort { // 对外暴露的排序方法 public static void mergeSort(int[] arr) { if (arr == null || arr.length <= 1) { return; } // 临时数组,避免递归中频繁创建数组 int[] temp = new int[arr.length]; sort(arr, 0, arr.length - 1, temp); } // 递归拆分 + 排序 private static void sort(int[] arr, int left, int right, int[] temp) { // 递归终止条件:子数组只有一个元素 if (left >= right) { return; } int mid = left + (right - left) / 2; // 防止溢出 sort(arr, left, mid, temp); // 排序左半部分 sort(arr, mid + 1, right, temp); // 排序右半部分 merge(arr, left, mid, right, temp); // 合并两个有序子数组 } // 合并两个有序区间 [left, mid] 和 [mid+1, right] private static void merge(int[] arr, int left, int mid, int right, int[] temp) { int i = left; // 左数组起始指针 int j = mid + 1; // 右数组起始指针 int k = left; // 临时数组指针 // 把两个有序子数组按顺序放入 temp while (i <= mid && j <= right) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } // 拷贝左数组剩余元素 while (i <= mid) { temp[k++] = arr[i++]; } // 拷贝右数组剩余元素 while (j <= right) { temp[k++] = arr[j++]; } // 把 temp 中排好序的部分复制回原数组 System.arraycopy(temp, left, arr, left, right - left + 1); } // 测试 public static void main(String[] args) { int[] arr = {8, 4, 5, 7, 1, 3, 6, 2}; System.out.println("排序前:"); for (int num : arr) { System.out.print(num + " "); } mergeSort(arr); System.out.println("\n递归归并排序后:"); for (int num : arr) { System.out.print(num + " "); } } }

2. 非递归版归并排序(迭代实现)

思路:

  1. 最小子数组长度 = 1开始,两两合并
  2. 子数组长度翻倍(1→2→4→8…)
  3. 直到合并成整个数组无递归,避免栈溢出,适合大数据量
public class MergeSortNonRecursive { public static void mergeSortNonRecursive(int[] arr) { if (arr == null || arr.length <= 1) { return; } int n = arr.length; int[] temp = new int[n]; int mergeSize = 1; // 初始合并单元长度:1 while (mergeSize < n) { // 每次从左到右依次合并两个长度为 mergeSize 的子数组 for (int left = 0; left < n; left += mergeSize * 2) { int mid = left + mergeSize - 1; // 右边界不能越界 int right = Math.min(left + mergeSize * 2 - 1, n - 1); // 只有左半边,无需合并 if (mid >= right) { break; } // 合并逻辑和递归版完全一样 merge(arr, left, mid, right, temp); } // 子数组长度翻倍 mergeSize *= 2; } } // 合并方法和递归版完全相同 private static void merge(int[] arr, int left, int mid, int right, int[] temp) { int i = left; int j = mid + 1; int k = left; while (i <= mid && j <= right) { if (arr[i] <= arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } while (i <= mid) { temp[k++] = arr[i++]; } while (j <= right) { temp[k++] = arr[j++]; } System.arraycopy(temp, left, arr, left, right - left + 1); } // 测试 public static void main(String[] args) { int[] arr = {8, 4, 5, 7, 1, 3, 6, 2}; System.out.println("排序前:"); for (int num : arr) { System.out.print(num + " "); } mergeSortNonRecursive(arr); System.out.println("\n非递归归并排序后:"); for (int num : arr) { System.out.print(num + " "); } } }

核心说明

  1. merge 方法两个版本的合并逻辑完全相同,是归并排序的核心。
  2. 递归 vs 非递归
    • 递归:代码简洁,易理解,大数据量可能栈溢出
    • 非递归:无栈溢出风险,效率更稳定
  3. 稳定性相等元素不交换顺序,是稳定排序

总结

  1. 递归版:自上而下拆分,代码简洁,适合学习理解
  2. 非递归版:自下而上合并,无栈溢出,适合生产环境
  3. 两个版本时间复杂度都是 O (n log n),都需要 O (n) 临时空间
  4. 复制代码可直接运行,输出排序结果
http://www.jsqmd.com/news/903300/

相关文章:

  • 2026年重庆漏水水管检测品牌评测:重庆隐蔽管道漏水检测/重庆专业地下管道测漏/四大工况实测对比 - 优质品牌商家
  • 漫威冠军对决战场模式:从节点理解到实战博弈的进阶指南
  • 沃尔玛购物卡回收需要注意什么?姐妹们这几点真的要记牢! - 京顺回收
  • 3大核心技术深度解析:Magisk如何重塑Android系统定制生态
  • 杭州闲置奢包回收怎么选?本地实测靠谱门店深度对比 - 奢侈品回收测评
  • PrusaSlicer终极指南:如何快速上手免费3D打印切片软件
  • 大模型多语言能力评估新范式:往返翻译与LiT基准的实践指南
  • 40块钱的电磁炉拆开看:电容触摸按键、IGBT功率管,这成本是怎么抠出来的?
  • 如何找到靠谱的香港爱格板全屋定制源头工厂?深圳四大品牌实测避坑指南 - 产品测评官
  • 系统化成长:如何通过审计、简化、增强与连接四步法优化个人工作流
  • 从零到一:在Cesium中创建酷炫的动态圆环(附完整配置流程与素材)
  • YgoMaster终极指南:三步开启免费离线游戏王大师决斗体验
  • 2026年 东莞GEO优化推广运营TOP5榜单:覆盖GEO推广/优化运营/深度营销的最新服务商推荐! - 品牌企业推荐师(官方)
  • iOS激活锁终极绕过:5步解锁iPhone/iPad完整方案
  • 2026成都合同纠纷律师事务所专业推荐推荐 - 优质品牌商家
  • 别死记硬背了!用Swift Playgrounds动态演示iOS底层原理(RunLoop/KVO/Runtime)
  • 腰果炒货机核心技术解析与加工企业选型推荐 - 优质品牌商家
  • 10分钟打造音乐动画LED矩阵:树莓派+Grablo可视化编程实战
  • 终极音乐解锁指南:免费工具打破音频格式限制
  • 告别枯燥理论:用Multisim仿真MC1496 DSB调制,快速验证电路参数与失真
  • 2026年 广东网站建设与运营推广TOP榜单:高端官网建设、抖音/1688代运营、AI搜索优化及爱采购推广服务深度解析 - 品牌企业推荐师(官方)
  • 2026年成都保洁外包公司TOP5:楼宇全包式物业、成都保洁公司、成都清洁外包、成都物业公司、成都物业外包、攀枝花保洁外包选择指南 - 优质品牌商家
  • BMS四层板通信EMC设计-如何做故障规避
  • Arduino与74HC595驱动多路RGB LED:蓝牙无线调光方案详解
  • Blender - 显卡选配
  • ChanlunX:通达信缠论分析插件终极指南 - 三分钟实现智能缠论可视化
  • 别再只用imshow了!用Matlab给黑白漫画上色:密度分割、彩虹编码、频域滤波三种方法实战对比
  • 别只用DateTime.Now了!Unity中处理系统时间的3个进阶技巧与常见坑点
  • 告别固定采样率!STM32F4自适应ADC采样策略详解(基于TIM触发与输入捕获)
  • AutoUnipus:如何用Python自动化工具将U校园学习时间减少90%?