归并排序
归并排序以O(NlogN)的最坏运行时间运行, 所比较的次数几乎是最优的。它是递归算法的一个好的例子。
这个算法中基本操作是合并两个已排序的表。因为这两个表是已排序的, 所以若将输出放到第三个表中,则该算法可以通过对输入数据一趟排序来完成。基本的合并算法是取两个输入数组A和B, 一个输出数组C, 以及三个计数器Actr、Bctr、Cctr,他们初始置于对应数组的开始端。A[Actr]和B[Bctr]中的较小者被拷贝到C中下一个位置, 相关的计数器向前推进一步。当两个输入表中有一个用完的时候, 则将另一个表剩余的数拷贝到C组。
例子:已知一个数组 24, 13, 26, 1, 2, 27, 38, 15
合并两个已排序的表时间显然是线性时间, 因为最多进行N-1次比较,其中N是元素的总数。为了看清这一点, 注意每次比较都把一个元素添加到C中, 但最后的比较除外。
而归并排序的策略是将一个一整块的表分割成二块表,然后再细分,
这就是典型的分治(divide-and-conquer)策略, 他将问题分成小问题然后递归求解。
package sort;
/*
* 归并排序:
* 归并排序以0(NlogN)最坏情形时间运行而所使用的比较次数几乎是最优的。
*
* 基本操作:是合并两个已排序的表。因为这两个表已排序
*/
public class Mesgesort<AnyType>{
private static <AnyType extends Comparable<? super AnyType>>
void mergeSort(AnyType[] a, AnyType[] 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);
}
}
//驱动程序
public static <AnyType extends Comparable<? super AnyType>> void mergeSort(AnyType[] a){
@SuppressWarnings("unchecked")
AnyType[] tmpArray = (AnyType[])new Comparable[a.length];
mergeSort(a, tmpArray, 0, a.length - 1);
}
private static <AnyType extends Comparable<? super AnyType>> void merge(AnyType[] a, AnyType[] tmp, int leftPos, int rightPos, int rightEnd){
int leftEnd = rightPos - 1;
int tmpPos = leftPos; //从起点开始
int numElement = rightEnd + 1;
while(leftPos <= leftEnd && rightPos <= rightEnd)
if(a[leftPos].compareTo(a[rightPos]) <= 0)
tmp[tmpPos++] = a[leftPos++];
else
tmp[tmpPos++] = a[rightPos++];
//如果左边还有的话, 那么就把左边的都加到后面
while(leftPos <= leftEnd)
tmp[tmpPos++] = a[leftPos++];
//如果右边还有剩余的话, 那么就把右边的都加到后面
while(rightPos <= rightEnd)
tmp[tmpPos++] = a[rightPos++];
System.out.println("第" + count++ + "次");
for(int i = 0; i < numElement; i++, rightEnd--){
a[rightEnd] = tmp[rightEnd];
System.out.print(tmp[i] + " ");
}
System.out.println();
}
private static int count = 1;
public static void main(String[] args){
Integer[] a = new Integer[]{24, 13, 26, 1, 2, 27, 38, 15};
mergeSort(a);
for (Integer integer : a) {
System.out.print(integer + " ");
}
}
}