1.概念
归并排序是建立在归并操作上的一种有效、稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
2.具体步骤
这里举个例子:给定一个无序数组[24,17,40,28,13,14,22,32,40,21,48,4,47,8,37,18]
(1)解决输入变化:分解输入,将原数组长度分解至每个子数组长度为1时天然有序,即分解原问题.
(2)构建有序数组:将每个子数组两两合并,得到新的有序的子数组,再两两合并新的子数组,递归解决子问题,最终得到新的有序数组。
3.归并排序的伪代码
MergeSort(A,left,right)
- 递归终止:仅有一个元素
- 计算子问题规模
- 递归求解子问题
- 合并子问题解
Merge(A,left,mid,right)
- 初始化
- 遍历子数组,进行合并
- 添加剩余元素保证有序
4.归并排序代码
void merge(int a[], int start, int mid, int end) {
int a1[end];
int i = start; // 第一个有序区的索引
int j = mid + 1; // 第二个有序区的索引
int k = start;
while (i <= mid && j <= end) {
if (a[i] <= a[j]) {
a1[k++] = a[i++];
}
else {
a1[k++] = a[j++];
}
}
while (i <= mid) { //处理第一个子序列剩余记录
a1[k++] = a[i++];
}
while (j <= end) { //处理第二个子序列剩余记录
a1[k++] = a[j++];
}
// 将合并结果传回数组a
for (i = start; i <= end; i++) {
a[i] = a1[i];
}
}
void mergeSort(int a[], int start, int end) {
if (start == end) {
return;
}
int mid = (end + start) / 2;
mergeSort(a, start, mid); // 递归排序a[start..mid]
mergeSort(a, mid + 1, end); // 递归排序a[mid+1..end]
// a[start..mid]和a[mid+1..end]是两个有序空间
// 将它们排序成一个有序空间a[start..end]
merge(a, start, mid, end);
}
5.归并排序的特点
(1)时间复杂度
归并排序算法每次将序列折半分组,共需要logn轮,因此归并排序算法的时间复杂度是O(nlogn)。
(2)空间复杂度
归并排序算法排序过程中需要额外序列去存储排序后的结果,所占空间是数组大小n,因此空间复杂度为O(n)。
(3)稳定性
归并排序算法在排序过程中,相同元素的前后顺序没有改变,所以归并排序是一种稳定排序算法。