package algorithms.sort;
import algorithms.lib.In;
import algorithms.lib.Out;
import algorithms.lib.StdRandom;
import algorithms.lib.TC;
/**
* 归并排序算法
*
* @author Qogir
* @since 2013/08/02
* @version 1.0
*
*/
public class Merge {
/**
* 归并 将一个数组的子数组进行归并
* @param a 指定的数组
* @param lo 起始位置的索引
* @param mid 中间位置的索引
* @param hi 结束位置的索引
*/
public static void merge(Comparable[] a, int lo, int mid,
int hi) {
int i = lo;
int j = mid + 1;
assert isSorted(a, lo, mid);
assert isSorted(a, mid+1, hi);
for (int k = lo; k <= hi; k++)
aux[k] = a[k];
for (int k = lo; k <= hi; k++) {
if (i > mid)
a[k] = aux[j++]; //左半边元素用尽
else if (j > hi)
a[k] = aux[i++]; //右半边元素用尽
else if (less(aux[j], aux[i]))
a[k] = aux[j++]; //右半边小于左边
else
a[k] = aux[i++]; //右半边大于左半边
}
assert isSorted(a, lo, hi);
}
/**
* 对指定的数组进行排序 <b>自顶向下</b>
* 通过不断的递归调用,将整个排序问题不断划分,直到最小规模,然后进行向上的归并
* @param a 指定的数组
*/
public static void sortUpToDown(Comparable[] a){
aux = new Comparable[a.length];
sort(a,0,a.length-1);
}
/**
* 对指定的数组进行排序 <b>自底向上</b><br>
* 这种实现并不是采用递归的形式,先是进行两两归并,然后四四...
* @param a 指定的数组
*/
public static void sortDownToUp(Comparable[] a){
int N = a.length;
aux = new Comparable[a.length];
for(int i = 1; i < N ; i = 2*i){
for(int lo = 0; lo < N-i; lo += 2*i)
merge(a,lo,lo+i-1,Math.min(lo+2*i-1, N-1));
}
}
/**
* 递归地对指定数组排序
* @param a 待排序数组
* @param lo 数组低位索引
* @param hi 数组高位索引
*/
private static void sort(Comparable[] a, int lo, int hi) {
if(hi <= lo)
return;
int mid = lo + (hi - lo)/2;
sort(a,lo,mid); //左半部分
sort(a,mid+1,hi);//右半部分
if(!less(a[mid],a[mid+1])) //这样可以减少比较次数,省去了对有序数组的归并
merge(a,lo,mid,hi); // 归并
}
/**
* 判断指定数组是否已经有序
*
* @param a
* 指定的数组
* @return true 已经排序,false 未排序
*/
private static boolean isSorted(Comparable[] a) {
return isSorted(a, 0, a.length - 1);
}
private static boolean isSorted(Comparable[] a, int lo, int hi) {
for (int i = lo + 1; i <= hi; i++)
if (less(a[i], a[i - 1]))
return false;
return true;
}
/**
* 判断指定的元素是否小于另一个元素
*
* @param a
* 元素1
* @param b
* 元素2
* @return true 如果 a < b,false 如果 a >= b
*/
private static boolean less(Comparable a, Comparable b) {
return a.compareTo(b) < 0;
}
/**
* 交换指定数组中的两个指定的元素
*
* @param a
* 包含待交换元素的数组
* @param i
* 第一个元素的索引
* @param j
* 第二个元素的索引
*/
private static void exch(Comparable[] a, int i, int j) {
Comparable tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/**
* 用于显示结果
*
* @param a
* 数据源
* @param time
* 排序时间
*/
private static void show(Comparable[] a, long time) {
int i = 0;
System.out.println("Data'length:" + a.length + "\tCast Time:" + time
+ "ms");
for (Comparable e : a) {
System.out.println(i++ + ":" + e);
}
System.out.println();
}
/* 用于显示结果
*
* @param a
* 数据源
* @param time
* 排序时间
*/
private static void show(Comparable[] a, long time,boolean writeToFile) {
int N = a.length;
int j = 0;
if(writeToFile){
Out out = new Out("/root/data/data.txt");
out.println("Data'length:"+N+" Cast time:"+time+" ms");
for(int i = 0 ; i < N; i ++){
out.println(j++ +" : "+a[i]);
}
out.close();
}
else{
Out out = new Out("/root/data/data.txt");
out.println("Data'length:"+N+" Cast time:"+time+" ms");
out.close();
}
}
public static void main(String[] args){
Double[] data = {0.0,1.0,3.0,7.0,10.2,15.9,4.0,6.9,7.1,8.56,9.88};
sortUpToDown(data);
show(data,0);
/*In in = new In("/root/data/algs4-data/8Kints.txt");
int [] data = in.readAllInts();
Integer[] a = new Integer[data.length];
for(int i = 0; i < a.length; i ++){
a[i] = data[i];
}*/
/*TC t = new TC();
sortDownToUp(a);
show(a,t.getElapsedMills(),true);*/
}
private static Comparable[] aux;
}
以上为完整的归并排序的代码,算法分析会继续进行