- 长度为N的数组排序所需时间和NlogN成正比
- 但缺点是所需额外空间和N成正比
所以是典型的以空间换时间的算法。
原地归并的抽象方法
|
|
自顶向下的归并排序
下面这段代码证明了:如果它能将两个子数组排序,它就能够通过归并两个子数组来将
sort()
方法的作用在于安排多次merge()
方法的调用顺序。
归并排序所需的时间和NlgN
成正比,只需要比遍历数组多个对数因子的时间就能将一个庞大的数组排序。缺点
是辅助数组所使用的额外空间和N的大小成正比。
改进:
- 对小规模子数组使用插入排序
- 测试数组是否有序
- 不将元素复制到辅助数组
MergeX.java implements these improvements.
自底向上的归并序列
|
|
自底向上的归并排序比较适合用链表组织的数据。
归并排序是一种渐进最优的基于比较排序的算法。
Creative Problems
Faster merge. Implement a version of merge() that copies the second half of a[] to aux[] in decreasing order and then does the merge back to a[]. This change allows you to remove the code to test that each of the halves has been exhausted from the inner loop. Note: the resulting sort is not stable.
private static void merge(Comparable[] a, int lo, int mid, int hi){ for(int i=lo; i <= mid; i++) aux[i] =a[i]; for(int j = mid+1; j <= hi; j++) aux[j] = a[hi-j+mid+1]; int i = lo,j = hi; for(int k = lo;k <= hi;k++) if(less(aux[j],aux[i])) a[k] = aux[j--]; else a[k] = aux[i++]; }
Improvements. Write a program MergeX.java that implements the three improvements to mergesort that are described in the text: add a cutoff from small subarrays, test whether the array is already in order, and avoid the copy by switching arguments in the recursive code.
- Inversions. Develop and implement a linearithmic algorithm Inversions.java for computing the number of inversions in a given array (the number of exchanges that would be performed by insertion sort for that array—see Section 2.1). This quantity is related to the Kendall tau distance; see Section 2.5.
Web Exercise(N)