走进数据结构之排序(七)---归并排序

xiaoxiao2021-02-28  105

一、归并排序算法分析

将n个元素的数据序列看成是由n个长度为1的排序子序列组成,反复将相邻的两个子序列归并成一个排序子序列,直到合并成一个序列,则排序完成。

二、代码实现

package top.einino.mergesort;

public class MergeSort {

//将X中分别以begin1, begin2开始的两个相邻子序列归并(升序)到Y中, 子序列长度为n     private static void merge(int[] X, int[] Y, int begin1, int begin2, int n){         int i = begin1, j = begin2, k = begin1;         //将X中两个相邻子序列归并到Y中         while(i<begin1+n && j<begin2+n && j<X.length){             //升序将较小值复制到Y中             if(X[i]<X[j]){                 Y[k++] = X[i++];             }else{                 Y[k++] = X[j++];             }         }         //将前一个子序列剩余元素复制到Y,序列长度可能不足n         while(i<begin1+n && i<X.length){             Y[k++] = X[i++];         }         //将后一个子序列剩余元素复制到Y中         while(j<begin2+n && j<X.length){             Y[k++] = X[j++];         }     } //一趟归并,将X中若干相邻子序列两两归并到Y中,子序列长度为n  private static void mergepass(int[] X, int[] Y, int n){         System.out.println("子序列长度n="+ n + " ");         for(int i=0; i<X.length; i+=2*n){             merge(X, Y, i, i+n, n);         }         print(Y);     }  //归并排序(升序)     private static void mergeSort(int[] X){         //Y数组长度同X数组         int[] Y = new int[X.length];         //排序子序列长度,初值为1         int n = 1;         while(n<X.length){             //一趟归并,将X中若干邻子序列归并到Y             mergepass(X, Y, n);             //子序列长度加倍             n*=2;             if(n<X.length){                 //一趟归并,将Y中若干相邻子序列再归并到X                 mergepass(Y, X, n);                 n*=2;             }         }     } //输出排序数组 private static void print(int[] keys) { for(int key : keys){ System.out.print(key+" "); } System.out.println(); } public static void main(String[] args) { int[] X = {97, 82, 75, 53, 17, 61, 70, 12, 61, 58, 26}; mergeSort(X); } }

三、形象的小例子

老师又来排队了!

初始队列:A学生197,B学生182,C学生175,D学生153,E学生117,F学生161,G学生170,H学生112,I学生161,J学生158,K学生126

老师开始第一趟排序

首先老师对所有学生进行相邻距离为1的学生分为一组,并且比较的是每组的前1位与后1位进行比较,分组情况如下:

第一组:A、B

第二组:C、D

第三组:E、F

第四组:G、H

第五组:I、J

第六组:K

进行第一组的排序,结果A>B、所以先将B拉出队伍排到第一位,再将剩下不用再进行排序的A拉出队伍排到B后面

进行第二组的排序,结果C>D,所以先将D拉出队伍排到A学生的后面,再将C学生排到D学生的后面

同理,对其他组进行排序:最后结果为

B学生182,A学生197,D学生153,C学生175,E学生117,F学生161,H学生112,G学生170,J学生158,I学生161,K学生126

老师进行第二趟排序,将上一趟排序的结果再进行分组相邻距离为2的分为一组,并且比较的是每组的前2位与后两位进行比较,分组情况如下:

第一组:B、A    \  D、C

第二组:E、F     \  H、G

第三组:J、I \ K

老师开始进行第一组排序,

首先进行B与D的比较,结果D<B,所以先将D学生拉出队伍,排到第一位,再将C与B进行比较,结果C<B,再把C拉出队伍,排到D的后面,然后依次把B、A排到C的后面

再进行第二组的排序

首先进行E与H的比较,结果E>H,所以行将H排到A学生的后面,再进行E与G的比较,结果E<G,再把E排到H的后面,再将F与G进行比较,结果F<G,所以把F排到E的后面,G依次排到F的后面

同理进行第三组的排序,结果为K、J、I

第二趟 排序的最后结果是D学生153,C学生175B学生182,A学生197,H学生112,E学生117,F学生161,G学生170,K学生126,J学生158,I学生161

老师进行第三趟的排序

首先进行分组,以相邻距离为4的分为一组,并且比较的是每组前4位与后4位的比较,分组情况如下:

第一组:D、C、B、A\H、E、F、G

第二组:K、J、I

进行第一组的排序,

进行D与H的比较,结果D>H,所以先将H拉出队伍排到第一个,再进行D与E的比较,结果D>E,将E排到H的后面,再进行D与F的比较,结果D<F,所以将D排到E的后面,再进行F与C的比较,结果F<C,所以把F排到D的后面,再进行C与G的比较,结果C>G,所以将G排到F的后面,因为没得进行比较了,所以依次把C、B、A排到G的后面

再进行第二组的排序,因为第一组只有3个人,还不到4个人,就无需进行比较了

所以第三趟排序结果为:H学生112,E学生117,D学生153,F学生161,G学生170,C学生175,B学生182,A学生197,K学生126,J学生158,I学生161

老师进行第四趟的排序

首先进行分组,以相邻距离为8的分为一组,并且比较的是每组前8位与后8位的比较,分组情况如下:

第一组:H、E、D、F、G、C、B、A\K、J、I

老师进行第一组的排序,也是唯一一组,首先进行H与K的比较,结果H<K,所以先把H拉出队伍,排到第一位,再进行E与K的比较,结果E<K,把E排到H的后面,再进行D与K的比较,结果D>K,所以把K排到E的后面,再进行D与J的比较,结果D<J,所以把D排到K的后面,再进行比较F与J,结果F>J,所以把J排到D的后面,再进行F与I的比较,结果F=I,所以把F排到J的后面,再进行I与G的比较,结果G>I,所以把I排到F的后面,然后因为没得比较,所以依次把G、C、B、A排到I的后面,

最后的排序结果为:H学生112,E学生117,K学生126,D学生153,J学生158,F学生161,I学生161,G学生170,C学生175,B学生182,A学生197,

四、归并排序的时间复杂度

n个元素归并排序,每趟比较n-1次,数据移动n-1次,进行log2(n)趟,时间复杂度为O(n*log2(n))

五、归并排序的空间复杂度

归并排序需要O(n)容量的附加空间,与数据序列的存储容量相等,空间复杂度为O(n)

六、稳定性

在归并排序算法中,关键字相等的元素会相遇进行比较,算法不改变它们的原有次序,所以,归并排序算法是稳定的

七、小结

本博文从归并排序算法分析,升序代码实现,老师排队的例子讲演,时间复杂度,空间复杂度以及稳定性介绍了归并排序的方方面面。

如果有疑问或者对该博文有何看法或建议或有问题的,欢迎评论,恳请指正!

转载请注明原文地址: https://www.6miu.com/read-70889.html

最新回复(0)