归并排序

5 篇文章 0 订阅
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;
}

以上为完整的归并排序的代码,算法分析会继续进行





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值