排序——归并排序

一、基本介绍

​ 归并排序是采用分治的策略实现排序的一种方法,即将问题分为若干个小问题,递归的去求解,然后将各个小问题合在一起,便完成整个排序过程。

二、排序过程

对数组arr = [9 , 4 , 5 , 3 , 7 , 1 , 6 , 2 ] 从小到大排序:

  1. 首先要将数组分成多个小的部分,整体图示如下

  2. 依次将每一部分合并为一个有序的序列,最后一次的合并如下图

    • 定义一个临时数组
    • 定义两个指针分别指向左部分第一个元素和右部分第一个元素
    • 进行第一次比较,然后拷贝小的值到临时数组的第一个元素;直到有一部分的元素已经比对完,最后将另一部分还剩于的元素拷贝到临时数组,最后将临时数组的值拷贝到原数组
    • 图解过程如下

三、代码实现

//分+合方法
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);
    }
}

/**
 * @param arr   排序的原始数组
 * @param left  左边有序序列的初始索引
 * @param mid   中间索引
 * @param right 右边索引
 * @param temp  做中转的数组
 */
public static void merge(int[] arr, int left, int mid, int right, int[] temp) {

    int i = left; // 初始化i, 左边有序序列的初始索引
    int j = mid + 1; //初始化j, 右边有序序列的初始索引
    int t = 0; // 指向temp数组的当前索引

    //先把左右两边(有序)的数据按照规则填充到temp数组,直到左右两边的有序序列,有一边处理完毕为止
    while (i <= mid && j <= right) {
        //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素,填充左边大数据到临时数组
        if (arr[i] <= arr[j]) {
            temp[t] = arr[i];
            t += 1;
            i += 1;
        } else { //反之,将右边有序序列的当前元素,填充到temp数组
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }
    }

    //把有剩余数据的一边的数据依次全部填充到temp
    while (i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temp
        temp[t] = arr[i];
        t += 1;
        i += 1;
    }
    while (j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temp
        temp[t] = arr[j];
        t += 1;
        j += 1;
    }
    //将temp数组的元素拷贝到arr
    t = 0;
    int tempLeft = left; //
    while (tempLeft <= right) {
        arr[tempLeft] = temp[t];
        t += 1;
        tempLeft += 1;
    }
}
posted @ 2020-02-19 21:14  xhanglog  阅读(178)  评论(0编辑  收藏  举报