数据结构与算法分析笔记(6)——归并排序

归并排序:要将一个数组排序,可以先(递归地)将它分成两半分别排序,然后将结果归并起来。归并排序最吸引人的性质是它能够保证将任意长度为N的数组排序所需时间和NlogN成正比;它的主要缺点则是它所需的额外空间和N成正比。

基本思想:

  • 将数组一分为(Divide array into two halves)
  • 对每部分进行递归式地排序(Recursively sort each half)
  • 合并两个部分(Merge two halves)

演示:


1. 给出原数组a[],该数组的lo到mid,mid+1到hi的子数组是各自有序的

2. 将数组复制到辅助数组(auxiliary array)中,给两部分的首元素分别以i和j的下标,给原数组首元素以k的下标


3. 比较i下标和j下标的元素,将较小值赋到k下标位置的元素内,然后对k和赋值的下标进行递增;
    该演示里j下标的元素比较小,于是将A赋到k的位置里,再对k和j递增,即j+1, k+1

4. 重复上述过程,直到比较完全部元素。

public class Merge {
	private static int[] aux;
	public static void sort(int[] a){
		aux = new int[a.length];
		sort(a,0,a.length-1);
	}
	private static void sort(int[] a,int lo,int hi){
		if(hi <=lo) return;
		int mid = lo + (hi-lo)/2;
		sort(a,lo,mid);//将左半边排序
		sort(a,mid+1,hi);//将右半边排序
		merge(a,lo,mid,hi);//归并结果
	}
	public static void merge(int[] a,int lo,int mid,int hi){
		//将a[lo..mid]和a[mid+1..hi]归并
		int i = lo, j = mid+1;
		for(int k= lo;k <= hi;k++)//将a[lo..hi]复制到aux[lo..hi]
			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 (aux[j] < aux[i])      a[k] = aux[j++];
			else                           a[k] = aux[i++];
		}
		
	}
}

性能分析:

算法复杂度为N*log(N)


优化:

问题:归并排序需要根据数组大小N开辟额外的内存

 

原地算法(in-place Algorithm):占用额外空间小于等于c log(N)的排序算法。

插入排序、选择排序、希尔排序都属于原地算法。归并排序不属于原地算法。Wiki参考

Kronrod在1969年发明了原地归并排序(in-place merge),不过看起来好像不是那么有用(Challenge for the bored)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值