[java数据结构]归并排序,超详细

在这里插入图片描述


前言


一、归并排序是什么?

归并排序的思路:
不断对数组进行二分,直到分组后序列的长度小于等于1,然后将两个子序列合并,得到一个有序的序列。

2-路归并实现的步骤:
1.先将数组分段,对每一段元素进行排序
2.创建一个新的数组,对两组排好序的序列进行合并
3.把元素从新的数组搬回原数组中

二、归并排序的实现

1.归并排序

代码如下:

public class mergeSort {
    
    
    public static void mergeSort(long[] array){
    
    

        mergeSortInternal(array,0,array.length);
        //数组Array为左闭右开区间
    }
    public static void mergeSortInternal(long[] array,int lowIndex,int highIndex){
    
    

        int size=highIndex-lowIndex;
        if(size<=1){
    
    
            return;
        }
        //区间都是左闭右开区间,middleIndex不包括在左边的数组中,包含在右边的数组中
        int middleIndex=(lowIndex+highIndex)/2;
        mergeSortInternal(array,lowIndex,middleIndex);
        mergeSortInternal(array,middleIndex,highIndex);

        合并两个有序区间(array,lowIndex,middleIndex,highIndex);

    }

2.合并两个有序序列

代码如下(示例):

 private static void 合并两个有序区间(long[] array,int lowIndex,int middleIndex,int highIndex){
    
    
        int size=highIndex-lowIndex;
        long[] extraArray=new long[size];
        int leftIndex=lowIndex;
        int rightIndex=middleIndex;
        int extraIndex=0;

        //两个序列都有元素时
        while(leftIndex<middleIndex&&rightIndex<highIndex){
    
    
            if(array[leftIndex]<=array[rightIndex]){
    
    
                extraArray[extraIndex]=array[rightIndex];
                leftIndex++;
                extraIndex++;
            }else{
    
    
                extraArray[extraIndex]=array[rightIndex];
                extraIndex++;
                rightIndex++;
            }
        }

        //开始有一个序列没有元素了
        if(leftIndex<middleIndex){
    
    
            while(leftIndex<middleIndex){
    
    
                extraArray[extraIndex++]=array[leftIndex++];
            }
        }else{
    
    
            while(rightIndex<highIndex){
    
    
                extraArray[extraIndex++]=array[rightIndex++];

            }
        }

3.将合并后的序列元素搬回去

        for(int i=0;i<size;i++){
    
    
            array[i+lowIndex]=extraArray[i];
        }

三、性能分析

时间复杂度:最好、最坏、平均都为O(n*log(n))
空间复杂度:都是O(log(n))
稳定性:稳定

四、海量数据的排序问题

前提:内存只有1G,需要排序的数据有100G
海量数据的特点就是:内存中无法把所有的数据全部放进去进行排序,所以需要外部排序(借助磁盘等外部存储进行的排序),而归并排序就是最常用的外部排序,简称多路排序。

1.把数据切割成n份(200份,每份512M);
2.分别对512M排序,因为内存已经放得下,任意的排序都可以,并且可以将任务分配给对个机器共同参与排序;
3.进行200路归并,同时对200份数据进行排序的过程,将每份文件中 最小的数字放到内存中(实际上也可以不止放入一个),将其中最小的数选出来,尾插到最后有序的文件中。


总结

1.当数据的元素个数比较少的时候,可以采用其他的排序方法(比如当元素个数小于16个时,建议使用插排),因为归并排序对于比较小的区间总是要不断地递归调用,开销比较大,不划算,因此不建议使用。
2.设计归并排序的时候,求数组的长度时,要注意每一小段区间下标的包含不包含问题,示例代码中采用的是左闭右开的区间。

猜你喜欢

转载自blog.csdn.net/m0_46551861/article/details/109280878