16、数据结构与算法 - 基础:排序算法之归并排序

1、归并排序介绍

归并排序(Merge Sort)是利归并的思想实现的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

2、归并排序原理

  • 申请空间,使它的大小为两个已经排序序列的和,这个空间用来存放合并后的序列
  • 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  • 比较两个指针所指向的元素,选择相对小的元素放到合并空间,并移动指针到下一个位置
  • 重复第三步步骤直到某个指针超出序列尾部
  • 另一个序列剩下的元素赋值合并到序列尾部

3、归并排序代码实现

public static void main(String[] args) {
   
     
    int[] arr = {
   
     8, 4, 5, 7, 1, 3, 6, 2}; // 合并的次数为 arr.length - 1
    mergeSort(arr, 0, arr.length - 1, new int[arr.length]);
    System.out.println(Arrays.toString(arr));
}

public static void mergeSort(int[] arr, int left, int right, int[] temp) {
   
     
    if (left < right) {
   
     
        // 取到中间索引
        int mid = (left + right) / 2;
        // 中间值左边分组,向左递归进行分解
        mergeSort(arr, left, mid, temp);
        // 右边分组向右递归
        mergeSort(arr, mid + 1, right, temp);
        merge(arr, left, mid, right, temp);
    }
}

public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
   
     
    int i = left; // 左边指针
    int j = mid + 1; // 右边指针
    int k = 0; // 临时数组指针
    // 循环条件为左边指针小于等于中间指针,右边指针小于等于最右边指针
    while (i <= mid && j <= right) {
   
     
        // 判断两个指针位置数据大小,存入临时数组中
        if (arr[i] <= arr[j]) {
   
     
            temp[k] = arr[i];
            k++;
            i++;
        } else {
   
     
            temp[k] = arr[j];
            k++;
            j++;
        }
    }
    // 循环结束后分别判断如果还有剩余数据的填充到 temp
    while (i <= mid) {
   
     
        temp[k] = arr[i];
        k++;
        i++;
    }
    while (j <= right) {
   
     
        temp[k] = arr[j];
        k++;
        j++;
    }
    // 将临时数组中的数据复制到 arr 原始数组中
    k = 0;
    while (left <= right) {
   
     
        arr[left] = temp[k];
        k++;
        left++;
    }
}