
本教程深入探讨如何在不依赖`java.util.arrays`包的情况下,实现递归归并排序算法。文章将详细介绍自定义数组切片(`copyofrange`替代)的方法,并提供标准的二路合并函数实现。此外,还将扩展讨论如何高效地实现三路合并函数,通过示例代码和专业讲解,帮助读者全面掌握归并排序的核心原理与实践技巧。
1. 归并排序(MergeSort)算法概述
归并排序是一种基于分治策略的高效排序算法。其基本思想是将待排序数组递归地分成两半,直到每个子数组只包含一个元素(自然有序),然后将这些有序的子数组两两合并,最终得到一个完全有序的数组。
归并排序的核心在于两个步骤:
分解(Divide):将当前数组一分为二。合并(Conquer/Merge):将两个已排序的子数组合并成一个更大的有序数组。
2. 自定义数组切片实现(替代 Arrays.copyOfRange)
在Java中,Arrays.copyOfRange是一个非常方便的工具,用于从现有数组中复制指定范围的元素到一个新数组。然而,在某些特定场景下,例如限制外部包依赖或出于学习目的,我们需要手动实现此功能。
Arrays.copyOfRange(original, from, to) 的行为是从 from(包含)索引到 to(不包含)索引复制元素。我们可以通过一个简单的循环来实现它:
立即学习“Java免费学习笔记(深入)”;
/** * 自定义数组切片方法,功能等同于 Arrays.copyOfRange * * @param original 原始数组 * @param from 起始索引(包含) * @param to 结束索引(不包含) * @return 包含指定范围元素的新数组 */private static int[] copyArray(int[] original, int from, int to) { // 检查索引有效性,防止越界或创建负长度数组 if (from original.length || from > to) { throw new IllegalArgumentException("Invalid 'from' or 'to' indices."); } int[] result = new int[to - from]; for (int i = from; i < to; i++) { result[i - from] = original[i]; } return result;}
将此自定义切片方法集成到归并排序中,mergeSort函数如下:
闪念贝壳
闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。
218 查看详情
public static void mergeSort(int[] A) { if (A.length > 1) { int mid = A.length / 2; // 使用自定义的 copyArray 方法代替 Arrays.copyOfRange // 左子数组包含从0到mid-1的元素 int[] leftArray = copyArray(A, 0, mid); // 右子数组包含从mid到A.length-1的元素 int[] rightArray = copyArray(A, mid, A.length); mergeSort(leftArray); mergeSort(rightArray); // 将排序后的左右子数组合并回原始数组A merge(A, leftArray, rightArray); }}
注意事项:
copyArray方法的效率可能低于JVM优化的Arrays.copyOfRange,尤其对于大型数组。正确处理from和to索引至关重要。to参数是独占的,这意味着它指定了复制停止的位置,但不包含该索引处的元素。例如,copyArray(A, 0, mid)将复制 A[0] 到 A[mid-1],长度为 mid。
3. 标准二路合并(Merge)函数实现
merge函数是归并排序的核心,它负责将两个已排序的子数组合并成一个更大的有序数组。合并过程中,我们通常需要三个指针:一个指向结果数组,两个分别指向两个待合并的子数组。
/** * 将两个已排序的子数组合并回主数组 * * @param mainArray 目标主数组,用于存放合并结果 * @param leftArray 已排序的左子数组 * @param rightArray 已排序的右子数组 */public static void merge(int[] mainArray, int[] leftArray, int[] rightArray) { int i = 0; // leftArray 的当前索引 int j = 0; // rightArray 的当前索引 int k = 0; // mainArray 的当前索引 // 比较左右子数组的元素,将较小的元素放入主数组 while (i < leftArray.length && j < rightArray.length) { if (leftArray[i] <= rightArray[j]) { mainArray[k++] = leftArray[i++]; } else { mainArray[k++] = rightArray[j++]; } } // 将 leftArray 中剩余的元素复制到主数组 while (i < leftArray.length) { mainArray[k++] = leftArray[i++]; } // 将 rightArray 中剩余的元素复制到主数组 while (j < rightArray.length) { mainArray[k++] = rightArray[j++]; }}
4. 扩展:三路合并(Merge)函数实现
将合并操作从两路扩展到三路,即同时合并三个已排序的数组,其基本思想仍然是不断从所有当前有元素的数组中选取最小的元素放入结果数组,并推进相应数组的指针。
实现三路合并的一种直接方法是维护三个数组的当前指针,并在每次迭代中找出这三个指针所指向元素中的最小值。
/** * 合并三个已排序的数组 * * @param a 第一个已排序数组 * @param b 第二个已排序数组 * @param c 第三个已排序数组 * @return 合并后的新数组 */public static int[] mergeArrays3(int[] a, int[] b, int[] c) { int[] result = new int[a.length + b.length + c.
以上就是Java递归归并排序与自定义数组切片及多路合并教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/986841.html
微信扫一扫
支付宝扫一扫