自顶向下的归并排序
自顶向下归并排序
图解
原理
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(divide and conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
算法分析
- 稳定性
归并排序是一种稳定的排序。
- 存储结构要求
可用顺序存储结构。也易于在链表上实现。
- 时间复杂度
对长度为n的文件,需进行 趟二路归并,每趟归并的时间为o(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是o(nlgn)。
- 空间复杂度
需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为o(n),显然它不是就地排序。
代码实现
public static void order4(int[] a) {
sort(a,0,a.length-1);
}
public static void sort(int[] data,int left,int right) {
if(left >= right) return;
//找出中间索引
int center = (left + right)/2;
//对左边数组进行递归
sort(data, left, center);
//对右边数组进行递归
sort(data, center+1, right);
//合并
merge(data,left,center,right);
}
public static void merge(int[] data,int left, int center,int right) {
//临时数组
int[] tmpArr = new int[data.length];
//右数组第一个元素索引
int mid = center + 1;
//third 记录临时数组的索引
int third = left;
//缓存左数组第一个元素的索引
int tmp = left;
while (left <= center && mid <=right) {
//从两个数组中取出最小的放入临时数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
//剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while(mid <= right) {
tmpArr[third++] = data[mid++];
}
while(left <= center) {
tmpArr[third++] = data[left++];
}
//将临时数组中的内容拷贝回原数组中
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}