归并排序(二)

108 阅读1分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

一、实现代码(java)

private int[] T;
private void mergeSort(int[] arr) {
    int n = arr.length;
    T = new int[n];
    sort(arr,0,n - 1);
}

private void sort(int[] arr,int left,int right) {
    if (left >= right) return;
    int mid = left + ((right - left) >> 1);
    sort(arr,left,mid);
    sort(arr,mid + 1,right);
    merge(arr,left,mid,right);
}

private void merge(int[] arr,int left,int mid,int right) {
    int start1 = left;
    int start2 = mid + 1;
    for (int i = left; i <= right; i++) {
        T[i] = arr[i];
    }
    for (int i = left; i <= right; i++) {
        if (start1 > mid)               arr[i] = T[start2++];
        else if (start2 > right)        arr[i] = T[start1++];
        else if (T[start1] < T[start2]) arr[i] = T[start1++];
        else                            arr[i] = T[start2++];

    }
}

二、描述

  • 归并排序的核心思想是将两个有序数组合成一个更大的有序数组,首先利用递归将一个大的数组逐步进行切分,直到大数组被切分成一个个很小的子数组。然后将小的数组进行排序,同时进行合并操作。
  1. 创建一个和排序目标数组长度一样的辅助数组,因为创建足够大的数组,在之后的排序操作时,就不会因为辅助数组不够大而再次创建新的数组,消除了创建数组过程中的时间开销。利用这个辅助数组可以先将前半部分排序,再将后半部分排序,然后在数组中移动元素而不需要额外的空间了。
private int[] T;
private void mergeSort(int[] arr) {
    int n = arr.length;
    T = new int[n];
    sort(arr,0,n - 1);
}
  1. 利用抽象实现排序并归并,这也是一个高效利用分治思想的典型例子。
private void sort(int[] arr,int left,int right) {
    if (left >= right) return;
    int mid = left + ((right - left) >> 1);
    sort(arr,left,mid);
    sort(arr,mid + 1,right);
    merge(arr,left,mid,right);
}
  1. 判断左右边界是否越界,越界了就终止当前方法。将子数组 arr[left...right] 复制到 T[left...right] 中,然后将 arr[left...mid] 和 arr[mid + 1...right] 合并成一个有序子数组并把结果存放到原数组中(arr[left...right])。
private void merge(int[] arr,int left,int mid,int right) {
    int start1 = left;
    int start2 = mid + 1;
    for (int i = left; i <= right; i++) {
        T[i] = arr[i];
    }
    for (int i = left; i <= right; i++) {
        if (start1 > mid)               arr[i] = T[start2++];
        else if (start2 > right)        arr[i] = T[start1++];
        else if (T[start1] < T[start2]) arr[i] = T[start1++];
        else                            arr[i] = T[start2++];

    }
}

三、最后

  • 以上内容参考自《算法第四版》。
  • 在归并中有自底向上自顶向下两种方法,具体可以去看一下书,效果可以看一下下面放的图,哈哈哈...呃。

IMG_20211120_195508.jpg

IMG_20211120_195629.jpg