归并排序采用分治思想,递归的缩小规模来进行排序。先分后合,分治减少了比较次数,而合并仅仅只是移动元素。在java中,进行一次元素比较可能是昂贵的,但是移动元素则是省时的(仅仅是引用的赋值,而不是对象的拷贝)
归并排序,运行时间是O (N log N)
事实上,它就是标准类库中泛型排序使用的算法
(C++中主要用的是快速排序)归并排序使用所有排序算法中最少的比较次数
java实现:
public class MergeSort {
public static <AnyType extends Comparable<? super AnyType>> void mergeSort(AnyType[] a) {
// 新建临时数组,保存归并结果
AnyType[] tmpArray = (AnyType[]) new Comparable[a.length];
mergeSort(a, tmpArray, 0, a.length - 1);
}
/**分而治之,递归**/
private static <AnyType extends Comparable<? super AnyType>> void mergeSort(
AnyType[] a, AnyType[] tmpArray, int left, int right) {
// 最后一种情况,只有两个数,有效程序只有最后一行,merge的时候就比较了两数的大小并排好序
if (left < right) {
// 截成两段分别排序,之后再合并
int center = (left + right) / 2;
mergeSort(a, tmpArray, left, center);
mergeSort(a, tmpArray, center + 1, right);
merge(a, tmpArray, left, center + 1, right);
}
}
/**合并**/
private static <AnyType extends Comparable<? super AnyType>> void merge(
AnyType[] a, AnyType[] tmpArray, int leftPos, int rightPos, int rightEnd) {
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int numElements = rightEnd - leftPos + 1;
while (leftPos <= leftEnd && rightPos <= rightEnd) {
if (a[leftPos].compareTo(a[rightPos]) <= 0) {
tmpArray[tmpPos++] = a[leftPos++];
} else {
tmpArray[tmpPos++] = a[rightPos++];
}
}
while (leftPos <= leftEnd) {
tmpArray[tmpPos++] = a[rightPos++];
}
while (rightPos <= rightEnd) {
tmpArray[tmpPos++] = a[leftPos++];
}
for (int i=0; i<numElements; i++, rightEnd--) {
a[rightEnd] = tmpArray[rightEnd];
}
}
}