Java排序算法之归并排序

标题:Java排序算法之归并排序

一、思想

  • 将n个记录看成是n个长度为1的有序子表组成
  • 将两两相临的子表归并一个有序子表

二、解题过程
第一步:

 * 将a[]看成是两个子表,
 * 一个起点为start1 ,长度为len1
 * 一个起点为start2 ,长度为len2
 * 对两个子表进行排序【利用两个子表已排好序的特性】
/**
	 *将a[]看成是两个子表,
	 *一个起点为start1 ,长度为len1
	 *一个起点为start2 ,长度为len2
	 *对两个子表进行排序【利用两个子表已排好序的特性】
	 * @param a
	 * @param start1
	 * @param len1
	 * @param start2
	 * @param len2
	 * @return
	 */
	public int[] mergesort(int[] a,int start1,int len1,int start2,int len2) {
		int i=start1;
		int j=start2;
		int[] nums=new int[a.length];
		int t=0;
		
		while(i<(start1+len1) && j<(start2+len2)) {
			if(a[i]<=a[j]) {
				nums[t++]=a[i];
				i++;
			}else {
				nums[t++]=a[j];
				j++;
			}
		}
		while(i<(start1+len1)) {
			nums[t++]=a[i++];
		}
		while(j<(start2+len2)) {
			nums[t++]=a[j++];
		}
		for(int p=0;p<t;p++) {
			a[p+start1]=nums[p];
		}
		
//		for(int in:a) {
//			System.out.print(in+" ");
//		}
//		System.out.println("  ");
		
		return a;
	}

第二步:

 * 调用上述的排序,
 * 第一个for循环,控制子表的长度
 * 第二个for循环,控制子表的数量
 * 每次的两个子表,长度不一定相等
 * 注意特例:1)长度为1时,* * *【单独出来的】,两两配对  -->最后面的一个*放置,等待下一次调用
 * 2)长度为2时,{*,*} *【此处长度小于len】两两配对   -->调用mergesor时,传入 的长度为2,1
	/**
	 * 调用上述的排序,
	 * 第一个for循环,控制子表的长度
	 * 第二个for循环,控制子表的数量
	 * 每次的两个子表,长度不一定相等
	 * 注意特例:1)长度为1时,* * *【单独出来的】,两两配对  -->最后面的一个*放置,等待下一次调用
	 * 2)长度为2时,{*,*} *【此处长度小于len】两两配对   -->调用mergesor时,传入 的长度为2,1
	 * @param a
	 * @return
	 */
	public int[] merge(int[] a) {
		for(int len=1;len<a.length;len*=2) {
			int sum=a.length;
			for(int j=0;j<a.length;) {
				int len1=len;
				int len2=len;
				if(sum-len>0) {
					sum-=len;
				}else break;
				
				if(sum-len>=0) {
					sum-=len;
				}else {
					len2=sum;
				}
				
				a=this.mergesort(a, j, len1, j+len1, len2);
				j=j+len1+len2;
			}
		}
		return a;
	}

完整代码:

/**
 * 测试归并排序
 * 将n个记录看成是n个长度为1的有序子表组成
 * 将两两相临的子表归并一个有序子表
 * 重复上述步骤
 * @author dell
 *
 */
public class MergeSort {
	/**
	 *将a[]看成是两个子表,
	 *一个起点为start1 ,长度为len1
	 *一个起点为start2 ,长度为len2
	 *对两个子表进行排序【利用两个子表已排好序的特性】
	 * @param a
	 * @param start1
	 * @param len1
	 * @param start2
	 * @param len2
	 * @return
	 */
	public int[] mergesort(int[] a,int start1,int len1,int start2,int len2) {
		int i=start1;
		int j=start2;
		int[] nums=new int[a.length];
		int t=0;
		
		while(i<(start1+len1) && j<(start2+len2)) {
			if(a[i]<=a[j]) {
				nums[t++]=a[i];
				i++;
			}else {
				nums[t++]=a[j];
				j++;
			}
		}
		while(i<(start1+len1)) {
			nums[t++]=a[i++];
		}
		while(j<(start2+len2)) {
			nums[t++]=a[j++];
		}
		for(int p=0;p<t;p++) {
			a[p+start1]=nums[p];
		}
		
//		for(int in:a) {
//			System.out.print(in+" ");
//		}
//		System.out.println("  ");
		
		return a;
	}
	
	/**
	 * 调用上述的排序,
	 * 第一个for循环,控制子表的长度
	 * 第二个for循环,控制子表的数量
	 * 每次的两个子表,长度不一定相等
	 * 注意特例:1)长度为1时,* * *【单独出来的】,两两配对  -->最后面的一个*放置,等待下一次调用
	 * 2)长度为2时,{*,*} *【此处长度小于len】两两配对   -->调用mergesor时,传入 的长度为2,1
	 * @param a
	 * @return
	 */
	public int[] merge(int[] a) {
		for(int len=1;len<a.length;len*=2) {
			int sum=a.length;
			for(int j=0;j<a.length;) {
				int len1=len;
				int len2=len;
				if(sum-len>0) {
					sum-=len;
				}else break;
				
				if(sum-len>=0) {
					sum-=len;
				}else {
					len2=sum;
				}
				
				a=this.mergesort(a, j, len1, j+len1, len2);
				j=j+len1+len2;
			}
		}
		return a;
	}
	
	@Test
	public void test() {
//		int[] a=new int[] {35,15,6,48,19,21,27};
//		int[] a=new int[] {26,5,77,1,61,11,59,15};
//		int[] a=new int[] {35,22,8,16,21,22,27};
//		int[] a=new int[] {32,42,7,48,15,48,12,18};
//		int[] a=new int[] {7,4,9,18,2,6,10};
		int[] a=new int[] {26,57,24,2,1,68,5,34,588,9,25,647};
		
		a = this.merge(a);
		for(int in:a) {
			System.out.print(in+" ");
		}
	}
	
	@Test
	public void test02() {
		int[] a=new int[] {35,15,6,48,19,21,27};
		this.mergesort(a, 0, 1, 1, 1);
		
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值