前言

归并排序,其实不难,捋清楚思路,把握他的核心思想:先分组后排序。
以下是我的个人理解和实现,希望对读者有帮助。

个人理解

我认为的归并排序,就是先分组后排序,具体来说,
分组 就是给你一个数组,你把它分组,分成每个元素都是一个组,例如:8个人,编号是从0~7,那么我们就把他们分成8组,然后在进行归并。关于这部分的实现:我用的是递归,就是我代码中的msort
归并:在分组完成的基础上,我们要将这些组合并起来,从 8 个组变成 1 个组,就完成了归并。采用的方式是两两比较,拿第一个组的第一个元素,和第二组的第一个元素,进行比较,将比较小的放到我们定义的临时数组里,聪明的人应该看出来了,这样比较的话,肯定会有一个组的元素率先用完,那样我们就把那个组剩余的元素,直接放进去就可以了。
关于这部分的实现,就是我代码中的merge方法

package data_structure;

import java.util.Arrays;
// 归并排序
public class IArraySort {
    public static void main(String[] args) {
        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
        System.out.println("归并前的数组" + Arrays.toString(arr));
        mergeSort(arr, arr.length);
        System.out.println("归并后的数组" + Arrays.toString(arr));
    }

    // 归并入口
    private static void mergeSort(int[] arr, int n) {
        // 定义一个临时数组
        int[] tempArr = new int[n];
        // 归并排序
        msort(arr, tempArr, 0, n - 1);
    }

    // 分组,把整个数组分成每个元素成为一组
    private static void msort(int[] arr, int[] tempArr, int left, int right) {
        // 如果只有一个元素,,那么就不需要进行排序了
        // 因为只有一个元素的区域,本来就是有序区域
        // 所以只有当左边小于右边时才需要分组
        if (left < right) {
            // 找中间点
            int mid = (left + right) / 2;
            //  递归划分左半区域
            msort(arr, tempArr, left, mid);
            // 递归划分右半区域
            msort(arr, tempArr, mid + 1, right);
            // 合并已经排序的位置
            merge(arr, tempArr, left, mid, right);
        }
    }

    // 合并
    private static void merge(int[] arr, int[] tempArr, int left, int mid, int right) {
        // 标记左半区域的一个未排序的元素
        int l_pos = left;
        // 标记右半区域的一个未排序的元素
        int r_pos = mid + 1;
        // 临时数组元素的下标
        int pos = left;
        // 合并
        while (l_pos <= mid && r_pos <= right){
            if (arr[l_pos] < arr[r_pos]){ // 左半区域第一个剩余元素更小
                tempArr[pos++] = arr[l_pos++];
            }else{ // 右半区域第一个剩余元素更小
                tempArr[pos++] = arr[r_pos++];
            }
        }
        // 以下时当其中一个组中的元素都被放完了,即没有比较了,另一个组的元素直接放进去就行
        // 合并左半区剩余的元素
        while(l_pos <= mid){
            tempArr[pos++] = arr[l_pos++];
        }
        // 合并右半区域剩余的元素
        while (r_pos <= right){
            tempArr[pos++] = arr[r_pos++];
        }
        // 把临时数组中合并的元素赋值回原来的数组
        while(left <= right){
            arr[left] = tempArr[left];
            left++;
        }
    }


}