Java实现归并排序的方法详解(包含递归+非递归)

 更新时间:2026年05月29日 08:43:07   作者:超梦dasgg  
归并归分n时间复杂度O(nlogn)的归并排序,递归与迭代实现,稳定排序适用于大数据处理,本文详细解析了递归与非递归版本的实现逻辑与应用场景,需要的朋友可以参考下

归并排序是分治思想的经典实现,核心是:拆分数组→合并有序子数组。 时间复杂度: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. 复制代码可直接运行,输出排序结果

以上就是Java实现归并排序的方法详解(包含递归+非递归)的详细内容,更多关于Java实现归并排序的资料请关注脚本之家其它相关文章!

相关文章

  • 一文盘点五种最常用的Java加密算法

    一文盘点五种最常用的Java加密算法

    大家平时的工作中,可能也在很多地方用到了加密、解密,比如:支付功能等,所以本文为大家盘点了Java中五个常用的加密算法,希望对大家有所帮助
    2023-06-06
  • java如何通过modbus4j实现modbus TCP通讯

    java如何通过modbus4j实现modbus TCP通讯

    Modbus协议包含RTU、ASCII、TCP三种类型,定义四个存储区(输出线圈、输入线圈、输出寄存器、输入寄存器)及其地址范围,支持读写功能,通过功能码01-04操作,仿真软件可模拟从站ID
    2025-07-07
  • Java如何将时间戳格式化为日期字符串

    Java如何将时间戳格式化为日期字符串

    这篇文章主要介绍了Java如何将时间戳格式化为日期字符串问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Spring超详细讲解创建BeanDefinition流程

    Spring超详细讲解创建BeanDefinition流程

    Spring在初始化过程中,将xml中定义的对象解析到了BeanDefinition对象中,我们有必要了解一下BeanDefinition的内部结构,有助于我们理解Spring的初始化流程
    2022-06-06
  • idea导入module的正确实现方法

    idea导入module的正确实现方法

    文章介绍了在IntelliJ IDEA中正确导入Spring Cloud项目module的方法:通过File→New→Module from Existing Sources选择路径并点击OK,随后右击pom.xml添加为Maven项目,最后运行Maven Install生命周期完成编译,强调操作步骤的重要性,避免因失误导致问题
    2025-07-07
  • 解决MyBatis中模糊搜索使用like匹配带%字符时失效问题

    解决MyBatis中模糊搜索使用like匹配带%字符时失效问题

    Mybatis是我们日常项目中经常使用的框架,在项目中我们一般会使用like查询作为模糊匹配字符进行搜索匹配,下面的Mapper.xml是我们使用like在项目中进行模糊匹配的常用方式,感兴趣的朋友跟随小编一起看看吧
    2021-09-09
  • java实现导出数据为zip压缩文件

    java实现导出数据为zip压缩文件

    这篇文章主要为大家详细介绍了java如何实现导出数据为zip压缩文件,并且解压后为json文件,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • springboot普通类中如何获取session问题

    springboot普通类中如何获取session问题

    这篇文章主要介绍了springboot普通类中如何获取session问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Arrays.sort如何实现降序排序

    Arrays.sort如何实现降序排序

    这篇文章主要介绍了Arrays.sort如何实现降序排序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Java线程和操作系统线程的关系解读

    Java线程和操作系统线程的关系解读

    这篇文章主要介绍了Java线程和操作系统线程的关系解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论