Java 归并排序

265 阅读3分钟

一、归并排序的原理

归并排序(Merge Sort)是一种基于分治思想的排序算法,其核心思想就是将原始的待排序序列逐渐划分成小的无序子序列,然后通过组合这些子序列得到有序的序列。

具体来说,归并排序的过程如下:

  1. 将原始的待排序序列划分成大小相等的两个子序列,分别进行递归排序。

  2. 将排好序的两个子序列进行合并,得到新的有序序列。

  3. 重复上述操作直到最终得到一个有序序列。

二、归并排序的实现

在 Java 中,我们可以使用以下代码来实现归并排序算法:

public static void mergeSort(int[] arr, int left, int right) {
    if (left < right) { // 当数组只有一个元素时结束递归
        int mid = (left + right) / 2; // 将数组分为两部分
        mergeSort(arr, left, mid); // 对左半部分进行递归排序
        mergeSort(arr, mid + 1, right); // 对右半部分进行递归排序
        merge(arr, left, mid, right); // 合并排好序的左半部分和右半部分
    }
}

public static void merge(int[] arr, int left, int mid, int right) {
    int[] tempArr = new int[arr.length]; // 创建临时数组
    int i = left; // 初始化左指针
    int j = mid + 1; // 初始化右指针
    int k = left; // 初始化新数组的索引
    while (i <= mid && j <= right) { // 当左右两个子序列都还有元素时循环
        if (arr[i] <= arr[j]) { // 如果左子序列当前元素小于等于右子序列当前元素,将左子序列当前元素添加到新数组中
            tempArr[k++] = arr[i++];
        } else { // 否则将右子序列当前元素添加到新数组中
            tempArr[k++] = arr[j++];
        }
    }
    while (i <= mid) { // 如果左子序列还有剩余元素,将其全部添加到新数组中
        tempArr[k++] = arr[i++];
    }
    while (j <= right) { // 如果右子序列还有剩余元素,将其全部添加到新数组中
        tempArr[k++] = arr[j++];
    }
    for (int m = left; m <= right; m++) { // 将新数组中的元素复制回原数组
        arr[m] = tempArr[m];
    }
}

在上述代码中,mergeSort() 方法是归并排序算法的入口,它采用递归的方式对左右两个子序列进行排序。merge() 方法则是用来将排好序的左半部分和右半部分进行合并的。

具体来说,我们先定义一个临时数组 tempArr,用来存储排好序的子序列。然后初始化左指针 i 和右指针 j,分别指向左半部分和右半部分的第一个元素。接着,我们从左到右遍历子序列,将其按照大小顺序添加到临时数组 tempArr 中。最后,将 tempArr 中的元素复制回原始数组 arr 中即可。

需要注意的是,在 merge() 方法中,我们需要将新数组中的元素复制回原数组 arr 中。这个过程需要使用一个循环,从左指针 left 开始遍历到右指针 right。

三、归并排序的时间复杂度

归并排序算法的时间复杂度为 O(nlogn),其中 n 是待排序序列的长度。这是因为归并排序算法在每一次递归中都将待排序序列划分为两个大小相等的子序列,并且每次合并操作的时间复杂度为 O(n)。因此,在最坏情况下,归并排序算法的时间复杂度为 O(nlogn)。

需要注意的是,归并排序算法的空间复杂度较高,因为它需要维护一个临时数组来存储排好序的子序列。在最坏情况下,临时数组的大小将会等于原始数组的大小,因此空间复杂度为 O(n)。