漫谈排序算法——归并排序

92 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

前言

在前面几篇文章,我们讲到了冒泡排序,插入排序这两种算法,它们的时间复杂度都比较高,适合小规模的数据排序的。所以今天我们来了解一下复杂度为O(nlogn)的排序算法——归并排序,它比较适合大规模的数据排序。比前面两种算法更加常用的。

归并排序简介

归并排序(Merge Sort)是指排序一个数组,我们需要把数组从中间切分成两部分,然后对切分出来的两部分分别进行排序,最后再将切分出来的两部分进行合并在一起,这样完成后整个数组都是有序的状态的。归并排序使用了分治的思想,对问题进行拆解,将大问题拆分成小的子问题来解决,小问题都解决了,大问题也随之解决了。我们的归并排序可以使用递归的代码来进行实现的。首先我们要推到对应的递归公式。

递推公式为:
merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))
 
终止条件为:
p >= r 不用再继续分解

终止条件为什么会等于p >= r呢,因为会将数组进行不断拆解,当数组的元素拆解到只有一个时,那么我们的这个拆解就结束了。数组为一个元素时,那么这个数组本身就有序了。然后再进行不断的合并,最终合并成有序的数组。代码实现如下:

public class MergeSort {

    public static void mergeSort(int[] a, int n) {
        if (n < 2) {
            return;
        }
        int mid = n / 2;
        int[] l = new int[mid];
        int[] r = new int[n - mid];

        for (int i = 0; i < mid; i++) {
            l[i] = a[i];
        }
        for (int i = mid; i < n; i++) {
            r[i - mid] = a[i];
        }
        mergeSort(l, mid);
        mergeSort(r, n - mid);

        merge(a, l, r, mid, n - mid);
    }

    public static void merge(
            int[] a, int[] l, int[] r, int left, int right) {

        int i = 0, j = 0, k = 0;
        while (i < left && j < right) {
            if (l[i] <= r[j]) {
                a[k++] = l[i++];
            }
            else {
                a[k++] = r[j++];
            }
        }
        while (i < left) {
            a[k++] = l[i++];
        }
        while (j < right) {
            a[k++] = r[j++];
        }
    }
}

总结

归并排序是一种采用分治思想的排序算法的,分治思想,对于大数据量是非常实用的。