归并排序

分治法:将原问题分解成几个规模较小的类似于原问题的子问题,递归的解决子问题,然后再合并这些问题的解来表示原问题的解。

分治模式基本步骤:分解 解决合并。

归并排序就是遵循分治模式的。归并排序是按照基本步骤可分为:

分解:分解n个数的序列成各具n / 2个元素的两个序列

解决:使用归并排序递归地排序两个子序列

合并:合并两个已排序的子序列以产生已排序的答案。


理解:进行辅助过程merge()时,实际上如同桌面上有两堆已经排好序的牌面朝上的牌,从上面的两张中选择最小的一张放在输出堆(牌面朝下)中,之后再比较新的两张牌的大小,重复进行。如果有一堆已经选完,那么剩余的部分就可以全部放入输出堆了。但是这两个牌堆不能每次都检查他为空,所以设置了一个”哨兵“。

参考代码:

package cn.nuist.jr.experiment;

import java.util.Arrays;

public class Merge {
	
	public static void main(String[] args) {
		int [] A = {5, 2, 4, 7, 1, 3, 2, 6};
		int i = 0, j = A.length - 1;
		mergeSort(A, i, j);
		System.out.println(Arrays.toString(A));	
	}
	
	private static void mergeSort(int[] a, int start, int end) {//先递归分解数组,再合并数组 算是完成了归并排序。
		if(start < end)
		{
		int mid = (start + end) / 2;
		mergeSort(a, start, mid);		
		mergeSort(a, mid + 1, end);
		merge(a, start, mid, end);	
		}	
	}
	
	private static void merge(int[] a, int p, int q, int r) {//p 起点   r 终点
		int i, j;
		int n1 = q - p + 1;
		int n2 = r - q;
		int [] L = new int[n1 + 1];
		int [] R = new int[n2 + 1];
		
		for(i = 0; i < n1; i ++){
			L[i] = a[p + i];
		}
		for(j = 0; j < n2; j ++){
			R[j] = a[q + j + 1];
		}
		L[n1] = Integer.MAX_VALUE;
		R[n2] = Integer.MAX_VALUE;//哨兵位置
		
		i = 0; j = 0;
		for(int k = p; k <= r; k ++){//注意此时需<= 否则会漏了数
			if(L[i] <= R[j]){
				a[k] = L[i];
				i = i + 1;
			}
			else{
				a[k] = R[j];
				j = j + 1;
			}
		}	
	}
	//Merge(A, q, p, r)//A表示数组,p, q, r 表示数组下标,且满足p<=q<r
	//假设两个子数组为A[p...q] 和 A[q+1...r]都已经排好序,在进行合并。
	//r - p + 1步	

	//伪代码:
	//n1 = q - p + 1;
	//n2 = r - q;
	//let L [1, n1 + 1] and R[1, n2 + 1] be new arrays
	//for i = 1 to n1
//	     L[i] = A[p + i -1]
	//for j = 1 to n2
//	     R[j] = A[q + j]  
	//L[n1 + 1] = 无穷
	//R[n2 + 1] = 无穷
	//i = 1
	//j = 1
	//for k = p to r
//	     if L[i] <= R[j]
//	    	A[k] = L[i]
//	    	i = i + 1
//	    else 
//		    A[k] = R[j]
//	    	j = j + 1
}

参考截图(取自书上,比较方便):

结果截图:
归并排序的效率算是比较高的,如果数列长为N,将数列分成小数列需要logN步,每一步都是一个合并有序数列的过程,时间复杂度可记作O(N),一共为O(N*logN)。


参考: 《算法导论》

以上就是本篇的基本内容。如果有什么可以改进的地方或者您发现了错误,请指出,谢谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值