归并排序
归并排序采用分治法,需要辅助空间来存放需要 排序的小数组 和 排序好的数组再整合的数组,因为使用了分路递归,所以时间复杂度都是O(nlogn),核心想法就是,假设有数组长度为10,一直对半拆分,最后剩2个数字排序,递归整合后再整合
下面代码将分为10小点讲解思想,对应的点在代码后的注释
其代码如下:
static int[] mergeSort(int...arr) {
if(arr.length<2) return arr; //-----------000------------
int mid = arr.length/2; //-----------111------------
int[] left = Arrays.copyOfRange(arr, 0, mid); //-----------222------------
int[] right = Arrays.copyOfRange(arr,mid, arr.length); //-----------333------------
return merge(mergeSort(left),mergeSort(right)); //-----------444------------
}
static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length+right.length]; //-----------555------------
for(int l=0,r=0,index=0;index<result.length;++index) {
if(l<left.length && r<right.length) { //-----------666------------
if(left[l]<right[r]) { //-----------777------------
result[index] = left[l++];
}else {
result[index] = right[r++];
}
}else if(l<left.length) { //-----------888------------
result[index] = left[l++];
}else if(r<right.length) { //-----------999------------
result[index] = right[r++];
}
}
return result;
}
讲解:
代码000:
对半拆分到不可再分后直接返回结果,否则继续拆分
代码111:
拆分点计算
代码222&代码333:
根据拆分点,拆分成左右2个数组
代码444:
递归拆分直到拆分成一个数字,最后调用合并函数 merge(int[] left,int[] right)
代码555:
归并方法,排序好的数组再整合的数组,再解释: 数组sum = 左数组 +右数组
代码666:
对数组sum 依次插入数据
代码777:
如果左数组的当前下标数对应值小于 右数组的当前下标数对应的值,数组sum 当前下位置的值等于左数组当前下标数对应的值,并且左数组的索引指标+1 ,反之亦如
代码888:
当右数组放完,直接放左数组的值过去,无需再比较
代码999:
当左数组放完,直接放右数组的值过去,无需再比较
其时间比较花费分析:
与java内部排序算法相比较:
数组长度为1000时:
手写归并排序--运行花费时间: 0ms
java内部排序工具--运行花费时间: 1ms
数组长度为10000时:
手写归并排序--运行花费时间: 4ms
java内部排序工具--运行花费时间: 2ms
数组长度为100000时:
手写归并排序--运行花费时间: 27ms //个人测试最大时间未59MS -- 最小20
java内部排序工具--运行花费时间: 10ms
数组长度为1000000时(3组数据):
手写归并排序--运行花费时间: 174ms
java内部排序工具--运行花费时间: 125ms
手写归并排序--运行花费时间: 154ms
java内部排序工具--运行花费时间: 48ms
手写归并排序--运行花费时间: 156ms
java内部排序工具--运行花费时间: 108ms
数组长度为10000000时(3组数据):
手写归并排序--运行花费时间: 1590ms
java内部排序工具--运行花费时间: 406ms
手写归并排序--运行花费时间: 1545ms
java内部排序工具--运行花费时间: 442ms
手写归并排序--运行花费时间: 1504ms
java内部排序工具--运行花费时间: 385ms
总结:数据越大排序时间约稳定,但速度还是比不过java的排序工具,自己总结的算法性能也不够以后会改进,也会找时间对java本身的排序工具写个文章
测试代码
public static void main(String[] args) {
int[] arr = new int[10000000];
Random r = new Random();
for(int i=0;i<arr.length;i++)
arr[i]=r.nextInt(100);
int[] arr1 =arr;
long currentTimeMillis1 = System.currentTimeMillis();
mergeSort(arr);
long currentTimeMillis2 = System.currentTimeMillis();
long currentTimeMillis3 = System.currentTimeMillis();
Arrays.sort(arr1);
long currentTimeMillis4 = System.currentTimeMillis();
System.out.println("手写归并排序--运行花费时间: "+(currentTimeMillis2-currentTimeMillis1)+"ms");
System.out.println("java内部排序工具--运行花费时间: "+(currentTimeMillis4-currentTimeMillis3)+"ms");
}