一起养成写作习惯!这是我参与「掘金日新计划 · 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++];
}
}
}
总结
归并排序是一种采用分治思想的排序算法的,分治思想,对于大数据量是非常实用的。