算法简介
归并排序(Merge Sort)比较占用内存,但却是一种效率高且稳定的算法。它是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用,分治法简单说就是分而治之,将一个大问题分解为小问题,将小问题解答后合并为大问题的答案。它将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
动图演示
代码实现
public class MergeSort {
// 归并排序
public static int[] mergeSort(int[] arr, int left, int right) {
// 如果 left == right,表示数组只有一个元素,则不用递归排序
if (left < right) {
// 把大的数组分隔成两个数组
int mid = (left + right) / 2;
// 对左半部分进行排序
arr = sort(arr, left, mid);
// 对右半部分进行排序
arr = sort(arr, mid + 1, right);
//进行合并
merge(arr, left, mid, right);
}
return arr;
}
// 合并函数,把两个有序的数组合并起来
// arr[left..mif]表示一个数组,arr[mid+1 .. right]表示一个数组
private static void merge(int[] arr, int left, int mid, int right) {
//先用一个临时数组把他们合并汇总起来
int[] a = new int[right - left + 1];
int i = left;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= right) {
if (arr[i] < arr[j]) {
a[k++] = arr[i++];
} else {
a[k++] = arr[j++];
}
}
while(i <= mid) a[k++] = arr[i++];
while(j <= right) a[k++] = arr[j++];
// 把临时数组复制到原数组
for (i = 0; i < k; i++) {
arr[left++] = a[i];
}
}
}
复杂度分析
若数列中有n个元素,则其中 ,其中n就是两个子区间合并的时间复杂度。
经过进一步推导,可以得到
我们假设 ,也就是说当 个元素的进行归并排序,达到递归终止条件时:,即:
因此时间复杂度为