自己实现的一个归并排序,加深下自己的理解...
归并排序应该是实用最多的吧,比快速排序慢,但是慢不了多少,它跟快速排序的时间是一个数量级,最重要的是它是稳定的,在至今的项目中,基本都实用归并排序
import java.util.List;
public class MergeSort {
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
if (list == null) {
return;
}
Object[] src = (Object[]) list.toArray();
Object[] dest = new Object[src.length];
// 为了循环利用空间,true表示src为临时空间,false表示dest为临时空间
// 因为一次归并后,临时空间的队列是结果
boolean srcIsTmp = false;
// 序列大小依次*2,进行归并排序
for (int i = 1; i < list.size(); i *= 2) {
if (srcIsTmp) {
sort(dest, src, i);
} else {
sort(src, dest, i);
}
srcIsTmp = !srcIsTmp;
}
Object[] merged = srcIsTmp ? dest : src;
list.clear();
for (Object o : merged) {
list.add((T) o);
}
}
/**
* 当小序列大小为n时,进行归并排序
* @param arr
* 要排序的序列
* @param tmp
* 临时序列,保存排序结果
* @param n
* 序列大小
*/
private static void sort(Object[] arr, Object[] tmp, int n) {
for (int i = 0; i < arr.length; i += 2 * n) {
sort(arr, tmp, n, i);
}
}
/**
* 对相邻的两个序列进行归并排序
*
* @param arr
* 要排序的序列
* @param tmp
* 临时序列,保存排序结果
* @param n
* 序列大小
* @param s
* 序列1起始位置
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void sort(Object[] arr, Object[] tmp, int n, int s) {
// 序列1起始位置,包括
int i1 = s;
// 序列1结束位置,不包括
int e1 = s + n;
// 如果序列1为最后的序列,即序列2不存在
if (e1 >= arr.length) {
System.arraycopy(arr, s, tmp, s, arr.length - s);
return;
}
// 序列2起始位置,包括
int i2 = e1;
// 序列2结束位置,不包括
int e2 = Math.min(e1 + n, arr.length);
// tmp序列下标
int i = s;
// 合并,比较两个队列
while (i1 < e1 && i2 < e2) {
if (((Comparable) arr[i1]).compareTo(arr[i2]) > 0) {
tmp[i++] = arr[i2++];
} else {
tmp[i++] = arr[i1++];
}
}
// 复制剩余的队列
for (int j = i1; j < e1; j++) {
tmp[i++] = arr[j];
}
for (int j = i2; j < e2; j++) {
tmp[i++] = arr[j];
}
}
}