咱们知道,java中泛型排序使用归并排序或TimSort。归并排序以O(NlogN)最坏时间运行,下面咱们分析归并排序过程及分析证实时间复杂度;也会简述为何java选择归并排序做为泛型的排序算法。java
假设输入数组A[一、七、九、13],B[五、八、1五、17],算法过程以下。1与5比较,1存入数组C中;接下来7与5比较,5存入C中。算法
接着7与8比较,7存入C中;9与8比较,8存入C中。数组
接着这样的过程进行比较,直到13与15比较,13存入C中。app
这时候A已经用完,将B中剩余的元素所有拷贝到C中便可。spa
从图中能够看出,合并两个排序表是线性的,最多进行N-1次比较(能够改变输入序列,使得每次只有一个数进入数组C,除了最后一次,最后一次至少有两个元素进入C)。对于归并排序,N=1的时候,排序结果是显然的;不然,递归将前半部分与后半部分分别归并排序。这是使用分治的思想。code
public class MergeSort {
public static void main(String[] args) {
Integer[] integers = {7, 1, 13, 9, 15, 5, 8,17};
System.out.println("原序列:" + Arrays.toString(integers));
mergeSort(integers);
System.out.println("排序后:" + Arrays.toString(integers));
}
public static <T extends Comparable<? super T>> void mergeSort(T[] a) {
//由于merge操做是最后一行,因此任什么时候候只须要一个临时数组
T[] tmpArray = (T[]) new Comparable[a.length];
mergeSort(a, tmpArray, 0, a.length - 1);
}
private static <T extends Comparable<? super T>> void mergeSort(T[] a, T[] tmpArray, int left, int right) {
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);
}
}
/**
* 合并左右数据方法
*
* @param a :原数组
* @param tmpArray : 临时数组
* @param leftPos :左边开始下标
* @param rightPos:右边开始下标
* @param rightEnd:右边结束下标
* @param <T>:元素泛型
*/
private static <T extends Comparable<? super T>> void merge(T[] a, T[] 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[leftPos++];
}
//复制后半部分
while (rightPos <= rightEnd) {
tmpArray[tmpPos++] = a[rightPos++];
}
// 回写原数组
for (int i = 0; i < numElements; i++, rightEnd--) {
a[rightEnd] = tmpArray[rightEnd];
}
}
}
咱们假设N是2的幂,咱们递归总能够均分为两部分。对于N=1,归并排序所用时间是常数,即O(1)。对于N个数归并排序的用时等于两部分时间之和再加上合并的时间。合并是线性的,由于最多使用N-1次比较。推导以下:orm
上面咱们假设了N=2k,对于N不是2的幂(一般都是这种状况),其实,结果都是差很少的,也只是最多再多一次过程而已。对象
归并排序与其余O(NlogN)排序算法相比,时间很依赖比较算法与在数组中移动元素(包括临时数组中)的相对开销。这是与语言环境有关的。对于Java来讲,进行比较可能比较耗时(使用Comparator);但移动元素属于引用赋值,不是庞大对象的拷贝。归并算法在全部流行的使用比较的算法中使用最少的比较次数。另外一个缘由是归并排序是稳定的,这在某些特殊的场景特别重要。blog
本篇经过画图详述了归并排序的过程,还经过数学证实归并排序时间复杂度稳定在O(NlogN);简谈了下java选择归并排序的缘由。java中对于基本类型的排序,使用的是快速排序。排序