归并排序的Java实现、性能分析以及适用场景

1.归并排序的Java实现:

代码如下:

package com.zm.testSort;
/**
 * 归并排序
 * @author zm
 */
public class MergeSort {
    public static void getMergeSort(int[] a) {
        if(a == null || a.length < 2) {
            return;
        }
        getMergeSort(a, 0, a.length-1);
    }
    public static void getMergeSort(int[] a, int low, int high) {
        if(high > low) {
            int mid = (high + low)/2;//获取中间值
            getMergeSort(a, low, mid);//分治
            getMergeSort(a, mid+1, high);//分治
            merge(a, low, mid, high);//合并两个子序列
        }
    }
    /**
     * 思想:将辅助数组分为两部分,如[a, b] [c, d],每个子序列是有序的,即a<b,c<d,因此,每回都是将
     * 第二部分的最小值c与第一部分的最小值a比较,如果c<a,则说明c是最小的,将c赋给原数组的第一个位置且用d与a比较,如果
     * c>a,则说明a是最小的,将a赋给原数组的第一个位置且再比较b与c。
     */
    public static void merge(int[] a, int low, int mid, int high) {//合并两个子序列
        int[] aux = new int[a.length];//创建辅助数组
        for(int k = low; k <= high; k++) {//将a数组赋值给辅助数组
            aux[k] = a[k];
        }
        int i = low;//用于操作辅助数组
        int j = mid + 1;//用于操作辅助数组
        int k = low;//用于保存正确排序的a数组的值
        for(;i <= mid && j <= high;k++) {
            if(aux[j] >= aux[i]) {//辅助数组的第二部分的第一个值开始,与第一部分的第一个值比较
                a[k] = aux[i++];//如果大于,将索引i的元素赋给a数组的索引k位置,同时索引i往后移
            }else {
                a[k] = aux[j++];//如果小于,将索引j的元素赋给a数组的索引k位置,同时索引j往后移
            }
        }
        while(i <= mid) {//如果此时i还在[0, mid]范围之内,说明剩下的i~mid之间的元素是最大的,将这些元素全部插入到a数组的最后
            a[k++] = aux[i++];
        }
        while(j <= high) {//如果此时j还在[mid+1, high]范围之内,说明剩下的j~high之间的元素是最大的,将这些元素全部插入到a数组的最后
            a[k++] = aux[j++];
        }

    }
    public static void main(String[] args) {
        int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34, 8, 23, 6, 9};
        getMergeSort(a);
        System.out.print("归并排序:");
        for(int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
}
}

2.归并排序的性能分析:

时间复杂度:
1. 最好情况:O(nlog2(n))
2. 平均情况:O(nlog2(n))
3. 最坏情况:O(nlog2(n))
空间复杂度:O(n)
稳定性:稳定(相同元素的相对位置不会改变)

3.适用场景

3.1:)若n较大,则应采用时间复杂度为O(nlog2(n))的排序方法:快速排序、堆排序或归并排序。
 快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
 堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
 若要求排序稳定,则可选用归并排序。但前面介绍的从单个记录起进行两两归并的排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子序列,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。

3.2:归并排序和快速排序一样,都采用了分治的思想。

猜你喜欢

转载自blog.csdn.net/zm13007310400/article/details/77427199