一、归并排序简介(自己理解)
自己的理解一句话:所谓归并排序,就是递归+合并。
引用百度百科对归并排序的定义:是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。点击打开链接
二、归并排序过程
过程:首先对数组进行无限对半分割,不断调用自身函数,也成递归。每次分割得到左右两个数组,对两边的数组分别进行排序,等到两边的数组都有序后,利用封装的merge函数对两个有序数组进行合并,最后得到整体有序。
其中无限分割最后应该分割到左右数组各只有一个元素,然后对两边的元素进行合并,再返回上层再合并。最终回到初始的数组上。
图解过程:
首先第一次分割,得到 [ 5 , 7 , 4 , 11 ] , [ 2 , 8 , 2 , 15 ] 两个数组,再往下分割,直至左右两个数组只有一个元素
分割完成后,对左右两边进行合并。
初始思路:新建一个数组,长度定义与原数组相同,定义三个指针,分别指向左数组第一个元素,右数组第一个元素和新定义数组的第一个元素,对原数组左右两部分分别遍历,想得到的较小的数传入新数组。最后将新数组的数据全部拷贝到原数组中。合并完成。
三、代码实现(Java)
public class MergeSort {
public static void main(String[] args) {
//获取指定长度的数组,getArray是自己封装的一个函数
long[] arr1 = getArray(50000,500000);
//获取两个时间相减,得到排序消耗的时间
long startTime = new Date().getTime();
mergeSort(arr1,0,arr1.length - 1);
long endTime = new Date().getTime();
int time = (int)(endTime - startTime);
//打印数组
printArray(arr1);
System.out.println("\n" + time + "ms");
}
//归并排序的公共方法
public static void mergeSort(long[] arr, int l, int r) {
// TODO Auto-generated method stub
long[] temp = new long[arr.length];
_mergeSort(arr, l, r, temp);
}
//归并排序的私有方法
private static void _mergeSort(long[] arr, int l, int r, long[] temp) {
// TODO Auto-generated method stub
if(r <= l) {
return;
}
int mid = (l + r) / 2;
_mergeSort(arr, l, mid, temp); //左边排序
_mergeSort(arr, mid + 1, r, temp); //右边排序
merge(arr,l, mid, r, temp);
}
//合并两个有序数组arr[l,mid],arr[mid+1,r]
private static void merge(long[] arr, int l, int mid, int r, long[] temp) {
// TODO Auto-generated method stub
int index, index1, index2;
index = 0;
index1 = l;
index2 = mid + 1;
while(index < r - l + 1) {
if(index1 > mid) {
temp[index ++] = arr[index2 ++];
}else if(index2 > r) {
temp[index ++] = arr[index1 ++];
}else if(arr[index1] < arr[index2]) {
temp[index ++] = arr[index1 ++];
}else {
temp[index ++] = arr[index2 ++];
}
}
for(int i = 0; i < r - l + 1; i ++) {
arr[i + l] = temp[i];
}
}
}
四、代码运行结果
1、对50000个元素的数组进行排序
平均耗时:15ms
2、对500000个元素的数组进行排序
平均耗时:100ms
3、对5000000个元素的数组进行排序
平均耗时:1010ms
五、时间复杂度
归并排序属于较稳定且较高效算法
时间复杂度为:O(N*logN)
六、总结
归并排序相比较选择排序,直接插入排序和冒泡排序的效率要高的多,不过代码中还有很多值得优化的地方。例如:应该在调用私有函数前创建一个公共的副本数组,这样就不用每次递归都new一个新的数组,节省资源,效率稍微高一点。