• 归并排序


    1、归并排序思想:

      归并排序的思想源于一个简单的思想,就是如果现在存在两个已经排好序的数组了,例如:{2, 3, 6, 8, 11},{1, 5, 7, 9},那么对这两个排序好的数组进行合并排序,就比较简单了,只需要创建一个临时的辅助数组,然后比较两个数组的头元素,2比1,那就将1先存入辅助数组,并且右边的数组指针向后移动一位。再比较两个数组的指针指向的元素,2比5小,那么2存进临时数组。不断的比较指针指向的元素,不断的往临时数组中存入,即可得到合并后的排序数组。

      基于这个思想,如果我们先把无序数组拆分成两个数组例如:{2, 3, 6, 8, 11, 1, 5, 7, 9,0}拆分成{2, 3, 6, 8, 11},{1, 5, 7, 9,0},若继续的进行拆分,直到所有的数组都拆分成了单个的元素即{2}{3}{6}{8}{11}{1}{5}{7}{9}{0},变成了单个元素之后,就相当于这单个元素有序了。然后再合并,两个单个的合并成两个元素的,两个两个元素的合并成多个元素的,多个元素的最终合并成总的数组,这时候数组一定就排序完成了。

      因此归并排序就是递归和分治思想的结合。

    比如初始数组:[24,13,26,1,2,27,38,15]

    ①分成了两个大小相等的子数组:[24,13,26,1]    [2,27,38,15]

    ②再划分成了四个大小相等的子数组:[24,13]   [26,1]    [2,27]    [38,15]

    ③此时,left < right 还是成立,再分:[24]   [13]   [26]    [1]    [2]     [27]    [38]   [15]

    此时,有8个小数组,每个数组都可以视为有序的数组了!!!,每个数组中的left == right,从递归中返回(从19行--20行的代码中返回),故开始执行合并(第21行):

    merge([24],[13]) 得到 [13,24]

    merge([26],[1]) 得到[1,26]

    .....

    .....

    最终得到 有序数组。

    2、代码:

    public class MergeSort {
    public static void main(String[] args) {
    int[] arr = {2, 3, 6, 8, 11, 1, 5, 7, 9,0};
    //先写merge,测试一下
    // merge(arr, 0, 4,7);
    //然后在拆分数组
    sort(arr);
    for (int i = 0; i < arr.length; i++) {
    System.out.print(arr[i] + ",");
    }
    System.out.println();

    }

    public static void sort(int[] arr) {
    sort(arr, 0, arr.length - 1);
    }

    //拆分数组,最终的目的就是拆成一系列单个元素的数组,为了递归,函数参数为:数组左起始指针,右终止指针
    public static void sort(int arr[], int left, int right) {
    //递归终止条件,将数组分成了只有单个元素的时候停止
    if (left < right) {
    int mid = left + (right - left) / 2;
    sort(arr, left, mid);
    sort(arr, mid + 1, right);
    merge(arr, left, mid + 1, right);
    }
    }

    //合并两个有序数组
    //传参:待排序数组、左数组起始指针、右数组起始指针、右数组终止指针
    public static void merge(int arr[], int leftp, int rightp, int rightBound) {
    int mid = rightp - 1;
    int[] tempArr = new int[rightBound - leftp + 1];
    int i = leftp;
    int j = rightp;
    int k=0;
    while (i <= mid && j <= rightBound) {
    if (arr[i] <= arr[j]) {
    tempArr[k++] = arr[i++];
    } else {
    tempArr[k++] = arr[j++];
    }
    }
    while (i <= mid) {
    tempArr[k++] = arr[i++];
    }
    while (j <= rightBound) {
    tempArr[k++] = arr[j++];
    }
    //将临时数组的值赋给arr
    for (int m = 0; m < tempArr.length; m++) {
    arr[leftp + m] = tempArr[m];
    }
    }
    }

    3、时间空间复杂度:

    时间复杂度为O(nlogn),空间复杂度为O(n)

    归并排序中,用到了一个临时数组,故空间复杂度为O(N)

    由归并排序的递归公式:T(N) = 2T(N/2) + O(N) 可知时间复杂度为O(NlogN)

    4、归并与快排比较:

      归并更加稳定,当数据量很大的时候仍然可以保持较快的效率,但快排会变成最坏的情形O(n^2)

     https://www.cnblogs.com/hapjin/p/5518921.html

    https://blog.csdn.net/qq_36442947/article/details/81612870

    视频讲解:https://www.bilibili.com/video/av48071817

    https://www.bilibili.com/video/av48142871/?spm_id_from=333.788.videocard.0

  • 相关阅读:
    安卓自带浏览器 position:fixed时 图片模糊问题
    建在ghost的blog
    javascript活动对象
    将json对象通过控制台保存到本地文件
    从用户体验出发的性能指标分析-DOM Ready(转)
    像诗一样的 Javascript 代码(转)
    给数组原型对象添加一个去重的方法,并返回去重后的数组
    如何避免FOUC(转)
    使用JS调用腾讯接口获取天气
    CSS好文推荐
  • 原文地址:https://www.cnblogs.com/guoyu1/p/12172479.html
Copyright © 2020-2023  润新知