Java不用递归实现归并排序

归并排序是一种高效的排序算法,采用分治法(Divide and Conquer)策略,将数组分成两半,对这两部分分别进行排序,最后合并两个已排序的数组。尽管归并排序通常使用递归实现,但我们可以通过迭代的方法来实现它,这样能够避免递归所带来的栈溢出风险。本文将为大家介绍如何用Java以迭代方式实现归并排序,并附上代码示例。

迭代归并排序的原理

迭代归并排序的思路是将数组看作一个个小的、已排序的子数组,并不断地将这些子数组合并成更大的已排序数组。具体步骤如下:

  1. 初始化:每个元素作为一个独立的子数组。
  2. 合并过程:从小到大的步长开始合并相邻的子数组,直到整个数组合并为一个已排序的数组。
  3. 步长的增加:在每轮合并后,步长加倍,继续合并更大的子数组。

Java代码示例

下面是一个示例代码,展示了如何在Java中以迭代方式实现归并排序。

import java.util.Arrays;

public class IterativeMergeSort {
    
    public static void merge(int[] arr, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;

        int[] leftArray = new int[n1];
        int[] rightArray = new int[n2];

        for (int i = 0; i < n1; ++i)
            leftArray[i] = arr[left + i];
        for (int j = 0; j < n2; ++j)
            rightArray[j] = arr[mid + 1 + j];

        int i = 0, j = 0;
        int k = left;

        while (i < n1 && j < n2) {
            if (leftArray[i] <= rightArray[j]) {
                arr[k] = leftArray[i];
                i++;
            } else {
                arr[k] = rightArray[j];
                j++;
            }
            k++;
        }

        while (i < n1) {
            arr[k] = leftArray[i];
            i++;
            k++;
        }

        while (j < n2) {
            arr[k] = rightArray[j];
            j++;
            k++;
        }
    }

    public static void mergeSort(int[] arr) {
        int n = arr.length;

        for (int currentSize = 1; currentSize < n; currentSize *= 2) {
            for (int leftStart = 0; leftStart < n - 1; leftStart += 2 * currentSize) {
                int mid = Math.min(leftStart + currentSize - 1, n - 1);
                int rightEnd = Math.min(leftStart + 2 * currentSize - 1, n - 1);

                if (mid < rightEnd) {
                    merge(arr, leftStart, mid, rightEnd);
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {38, 27, 43, 3, 9, 82, 10};
        System.out.println("原始数组: " + Arrays.toString(arr));
        mergeSort(arr);
        System.out.println("排序后的数组: " + Arrays.toString(arr));
    }
}

旅行图

让我们用图表定义这一过程,便于理解。

journey
    title 归并排序的过程
    section 初始化
      每个元素作为子数组: 5: 然后
    section 合并
      1: 子数组合并到2: 5: 然后
      子数组合并到4: 6: 然后
    section 完成
      所有子数组合并: 7: 然后

总结

通过迭代实现归并排序,我们克服了使用递归时可能遇到的问题,如栈溢出、性能开销等。尽管实现过程稍显复杂,但只需注意合并操作的细节,就能顺利完成。归并排序的时间复杂度为O(n log n),在处理大规模数据时尤为有效。希望这篇文章和示例代码能够帮助你更好地理解归并排序及其迭代实现。