当前位置:   article > 正文

八大排序之归并排序(建议与快排一起看)_归并排序中排序结果为一样的数字是什么情况?

归并排序中排序结果为一样的数字是什么情况?

排序算法

冒泡排序

简单选择排序

直接插入排序

希尔(shell)排序

快速排序

归并排序

堆排序

归并排序

排序原理:

  1. 尽可能的将一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。
  2. 将相邻的两个子组进行合并成一个有序的大组;
  3. 不断的重复步骤2,直到最终只有一个组为止。

在这里插入图片描述
对最后合并细化分析,核心代码Merge
在这里插入图片描述

Java代码

import java.util.Arrays;
public class MergeSort {

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

    private static void sort(int[] a,int lo, int hi){
        if(lo>=hi) return;
        int mid = lo + (hi - lo)/2;
        sort(a,lo,mid);
        sort(a,mid+1,hi);
        //合并两个数组
        merge(a,lo,mid,hi);
    }
    private static void merge(int[] a, int lo,int mid ,int hi ){
        //指向辅助数组的指针。
        int i = lo;
        //定义第一个数组的指针,初始指向第一个元素;
        int p1 = lo;
        //定义第二个数组的指针,初始指向第一个元素
        int p2 = mid+1;

        //比较两个数组指针指向的元素的大小,哪个小,就放入arr数组
        while(p1<=mid&&p2<=hi){
            if(a[p1]<a[p2]){
                arr[i++]=a[p1++];
            }else{
                arr[i++]=a[p2++];
            }
        }
        //如果数组二遍历完,数组一没完
        while(p1<=mid){
            arr[i++] = a[p1++];
        }
        //如果数组一遍历完,数组二没完
        while(p2<=hi){
            arr[i++] = a[p2++];
        }

        //拷贝数组
        for (int i1 = lo; i1 <= hi; i1++) {
            a[i1] = arr[i1];
        }

    }

    public static void main(String[] args) {
        int[] a = {8, 4, 5, 7, 1, 3, 6, 2};
        sort(a);
        System.out.println(Arrays.toString(a));
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

算法复杂度分析

O(nlogn)

归并排序是分治思想的最典型的例子,上面的算法中,对a[lo…hi]进行排序,先将它分为a[lo…mid]和a[mid+1…hi]
两部分,分别通过递归调用将他们单独排序,最后将有序的子数组归并为最终的排序结果。该递归的出口在于如果
一个数组不能再被分为两个子数组,那么就会执行merge进行归并,在归并的时候判断元素的大小进行排序。
在这里插入图片描述
用树状图来描述归并,如果一个数组有8个元素,那么它将每次除以2找最小的子数组,共拆log8次,值为3,所以树共有3层,那么自顶向下第k层有2^k个子数组,每个数组的长度为2^(3-k),归并最多需要2^(3-k)次比较。因此每层的比较次数为 2^k * 2^(3-k)=2^3,那么3层总共为 3*2^3。

假设元素的个数为n,那么使用归并排序拆分的次数为log2(n),所以共log2(n)层,那么使用log2(n)替换上面32^3中 的3这个层数,最终得出的归并排序的时间复杂度为:log2(n) 2^(log2(n))=log2(n)*n,根据大O推导法则,忽略底数,最终归并排序的时间复杂度为O(nlogn).

归并排序需要申请额外的数组空间,导致空间复杂度提升,是典型的以空间换时间的操作。

稳定性

稳定的

归并排序在归并的过程中,只有arr[i]<arr[i+1]的时候才会交换位置,如果两个元素相等则不会交换位置,所以它
并不会破坏稳定性,归并排序是稳定的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/454815
推荐阅读
相关标签
  

闽ICP备14008679号