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

目录

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

[2. 非递归版归并排序(迭代实现)](#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. 复制代码可直接运行,输出排序结果
相关推荐
我是一颗柠檬14 小时前
【JDK8新特性】JDK8实战与面试高频考点汇总Day12
java·开发语言·后端·面试·职场和发展
EIConferenceEmma14 小时前
【合作EI期刊 | IEEE出版 | 中国石油大学(华东)主办】第六届先进算法与神经网络国际学术会议(AANN 2026)
人工智能·神经网络·算法·机器学习
Brilliantwxx14 小时前
【算法题】 面试级别的二叉树题目OJ复习(下)
数据结构·c++·算法·leetcode·面试·哈希算法·推荐算法
疯狂成瘾者14 小时前
常见的优化查询速度方法
java
YOU OU14 小时前
Spring事务和事务传播机制
java·数据库·spring
菜菜的顾清寒14 小时前
力扣100(38)堆-数组中的第K个最大元素
算法·leetcode·排序算法
全球通史14 小时前
Jetson Nano 双摄像头芯片检测视觉系统:小尺度难定位问题解决,从零开始实现教程说明
嵌入式硬件·算法·ubuntu·性能优化
千寻girling14 小时前
机器学习 | 监督学习算法(了解) | 尚硅谷学习
开发语言·人工智能·后端·python·学习·算法·机器学习
强盛机器学习~14 小时前
2026年SCI一区新算法-灰叶猴优化算法(GLO)-公式原理详解与性能测评 Matlab代码免费获取
算法·matlab·进化计算·群体智能·智能优化算法·元启发式算法