数据结构之 归并排序(算法思想 、复杂度分析)

归并排序是一个时间复杂度为O(nlogn)的排序算法

归并排序的核心思想如下:
在这里插入图片描述
如果要排序一个数组,先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。

归并排序使用的就是分治思想。
分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。
小的子问题解决了,大问题也就解决了。

首先使用递归实现归并排序:

private static void mergeInternal(int[] array,int low,int high)
 {
     if(low >= high){
         return;
     }
     int mid = (low+(high-low)/2);
     //左边小数组
     mergeInternal(array,low,mid );
     //右边小数组
     mergeInternal(array,mid + 1,high);
     //合并
     merge(array,low,mid,high);
}

合并函数的实现:

在这里插入图片描述

  • 如图所示,申请一个临时数组 tmp,大小与 array[p…r]相同。
  • 用两个游标 i 和 j,分别指向array[p…mid]和 array[mid+1…r]的第一个元素。
  • 比较这两个元素 array[i] 和 array[j],如果 array[i]<=array[j],就把 array[i] 放入到临时数组 tmp,并且 i 后移一位,否则将 array[j] 放入到数组tmp,j 后移一位。
  • 继续上述比较过程,直到其中一个子数组中的所有数据都放入临时数组中,再把另一个数组中的数据依次加入到临时数组的末尾,这个时候,临时数组中存储的就是两个子数组合并之后的结果了。
  • 最后再把临时数组 tmp 中的数据拷贝到原数组 array[p…r] 中。

eg:归并排序代码实现

public static void merge(int[]array ,int p,int q ,int r){
     int i = p;
     int j = q+1;
     int[] temp = new int[r-p+1];
     int k = 0;
     //此时俩个数组均有元素
     while(i <=q && j<= r){
         if(array[i] <= array[j]){
             temp[k++] = array[i++];
         }else{
             temp[k++] = array[j++];
         }
     }
     //判断当前还有哪个数组没有走完
     int start = i;
     int end = q;
     //假如第二个小数组没有走完
     if(j <= r){
         start =j;
         end = r;
     }
     //把剩余元素直接放置在temp数组即可
    while(start <= end){
         temp[k++] = array[start++];
    }
    //将临时空间中已经合并好的数组拷贝回原数组
    for(i = 0;i < r-p+1;i++){
         array[p+i] = temp[i];
    }
    
public static void mergeSort(int[] array){
    long start = System.currentTimeMillis();
    int n  =array.length;
    if(n <= 1){
        return;
    }
    int mid = n / 2;
    mergeInternal(array,0,  n - 1);
    long end = System.currentTimeMillis();
    System.out.println("归并排序耗时:"+(end - start)+"毫秒");
}

算法总结:

  • 在合并的过程中,如果 A[p…q] 和 A[q+1…r] 之间有值相同的元素,那我们可以像伪代码中那样,先把A[p…q] 中的元素放入 tmp 数组。这样就保证了值相同的元素,在合并前后的先后顺序不变。所以,归并排序是一个稳定的排序算法
  • 归并排序的时间复杂度是 O(nlogn)。
    从我们的原理分析和伪代码可以看出,归并排序的执行效率与要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是 O(nlogn)
  • 每次合并操作都需要申请额外的内存空间,但在合并完成之后,临时开辟的内存空间就被释放掉了。在任意时刻,CPU 只会有一个函数在执行,也就只会有一个临时的内存空间在使用。临时内存空间最大也不会超过 n 个数据的大小,所以空间复杂度是 O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值