package sort;
import utils.Utils;
import java.lang.reflect.Array;
import java.util.Arrays;
public class MergeSort{
public <T extends Comparable<T>> void sort(T[] arr) {
sort(arr,0,arr.length-1);
}
private <T extends Comparable<T>> void sort(T[] arr, int l, int r) {
//finalConditon
if (l==r)
return;
int mid=l+(r-l)/2;
sort(arr,l,mid);
sort(arr,mid+1,r);
//左半部分、右半部分分别排序好。然后合并
merge(arr,l,mid,r);
}
private <T extends Comparable<T>> void merge(T[] arr, int l, int mid, int r) {
/* 复制一份数组,设置三个索引位置。logN merge完成*/
int i=l;
int j=mid+1;
T[] arr1=Arrays.copyOf(arr,arr.length);
/* doesnt work because Object cant cast to Comparable,T is a Comparable */ //this way works:T[] arr1=(T[]) Array.newInstance(arr.getClass().getComponentType(),arr.length);
//T[] arr1= (T[])new Object[arr.length];
System.arraycopy(arr,0,arr1,0,arr.length);
for (int k = l; k <=r; k++) {
if (i>mid){
arr[k]=arr1[j++];
}
else if (j>r)
arr[k]=arr1[i++];
else if (arr1[i].compareTo(arr1[j])<0)
arr[k]=arr1[i++];
else
arr[k]=arr1[j++];
}
}
public static void main(String[] args) {
Integer[] arr= Utils.generateIntArray(1000);
System.out.println(Arrays.toString(arr)
);
new MergeSort().sort(arr);
System.out.println(Arrays.toString(arr)
);
}
}
归并的改进点:
当需要排序的数组<=15时候,使用插入排序。这点改进将会给排序带来巨大的提升。说明算法没有好坏,每个算法都有其用武之地。根据不同的数量级确定不同的算法。
10000个数据排序的耗时对比:sort.MergeSortTime:110、sort.MergeSortPlusWithInsertionTime:7
//finalConditon
/*if (l==r)
return;*/
if ((r-l)<=15){
for (int i = l+1; i < r+1; i++) {
for (int j=i;j>l&&arr[j].compareTo(arr[j-1])<0;j--){
swap(arr,j,j-1);
}
}
return;
}
自下而上的归并排序
以上归并算法依赖于数组的下标随机访问,但是如果需要排序的数据不是数组,而是链表,就需要另一种归并方式。
@Override
public <T extends Comparable<? super T>> void sort(T[] arr) {
for (int sz=1;sz<=arr.length;sz=sz*2){
//按顺序把sz个元素分别排序。
// 处理两处边界越界问题。1、i+sz-1 要小于n-1;2、(i+sz+sz-1)<n-1;
for (int i=0;i<arr.length;i=i+sz+sz-1){
merge(arr,i,i+sz-1,Math.min(i+sz+sz-1,arr.length-1));
}
}
}