Java排序之归并排序

归并排序有两种方式:采用递归的方式,从顶向下递归。采用非递归方式,两两归并,自底向上。

归并排序的核心都是归并操作:

1.申请空间,使其大小为两个已排序的数组大小之和,用来存放排序之后的数组。

2.复制数组,将数组a复制到辅助数组aux

2.分别指定已排序的两个数组头结点。

3.分别比较两个数组头元素,将较小值放入数组中。

4.重复3,直至全部排序完。

package Suanfa;
import Suanfa1;
public class Merge1 {
	private static Comparable[] aux;
	public static void merge(Comparable[] a,int lo,int mid,int hi) {
		//Comparable[] aux=new Comparable[a.length];
		//将两个已排序的数组[lo,mid]和[mid+1,hi]合并
		int i=lo;//定义两个数组的头结点,之后不断的移动两个数组的头结点
		int j=mid+1;
		for (int k=lo;k<=hi;k++) {
			aux[k]=a[k];
		}
		for (int l=lo;l<=hi;l++) {
			if(i>mid) a[l]=aux[j++];
			else if(j>hi) a[l]=aux[i++];
			else if(Suanfa1.less(aux[j], aux[i])) a[l]=aux[j++];
			else a[l]=aux[i++];
		}
	}
	public static void sort(Comparable[] a) {
		aux=new Comparable[a.length];
		sort(a,0,a.length-1);
	}
	public static void sort(Comparable[] a, int lo, int hi) {
		if(hi<=lo) return;//先写出递归基
		int mid=lo+(hi-lo)/2;
		//sort(a,lo,hi);
		sort(a,lo,mid);
		sort(a,mid+1,hi);
		merge(a,lo,mid,hi);
	}
	public static void Msort(Comparable[] a) {
		int N=a.length;
		aux=new Comparable[a.length];
		for (int sz=1;sz<N;sz*=2) {//1和1合并变为2
			for (int lo=0;lo<N-sz;lo+=sz+sz) {
				merge(a,lo,lo+sz-1,Math.min(lo+sz+sz-1, N-1));//防止最后一个节点超出范围
			}
		}
	}
	public static void main(String[] args) {
		String[] a= {"B","D","A"};
		//sort(a);
		Msort(a);
		Suanfa1.show(a);
	}
	
}

归并排序的递归实现方法:

1.将一个数组的排序方式,变化为两个数组的合并方式。只要将两个数组都分别排好顺序了,之后再将两个数组合并那么最终的结果就是有序的。

2.利用一个辅助数组,aux,先将原有数组复制到aux中,然后每次将归并好的数组添加到原有数组中。给辅助数组定义两个指针,分别指向lo和mid+1,这样就可以将两个数组合并。

class paixu{
    Comparable[] aux;
    public static void sort(Comparable[] a){
        aux=new Comparable[a.length];
        sort(a,0,a.length-1);
    }
    public static void sort(Comparable[] a,int lo,int hi){
        if(lo>=hi) 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(Comparable[] a,int lo,int mid,int hi){
        //将两个已排序的数组合并[lo,mid] [mid+1,hi]合并为[lo,hi]
        for(int i=lo;i<=hi;i++){
            aux[i]=a[i];
        }
        int k=lo;
        int j=mid+1;
        for(int l=lo;l<=hi;l++){
            if(j>mid) a[l]=aux[k++];
            if(k>hi) a[l]=aux[j++];
            if(aux[j]<aux[k]) a[l]=aux[j++];
            else a[l]=aux[k++];
        }
    }
}

非递归实现方法:从底部向上,关键操作也是merge将一排需的数组合并。但是是从1 1合并为2,2 2合并为4,4 4合并为8

这里两个注意点:1.每次两两合并的大小都要翻倍,知道sz<len

2.对于每个sz都要从到到尾合并,关键是这里的每次合并头节点的增长,第一次lo=0,即将merge(a,0,sz-1,sz+sz-1)合并,第二次lo=sz+sz,....第三次lo=sz+sz+sz+sz+sz,即每次lo增长也是翻倍。

    public static void Msort(Comparable[] a){
        int len=a.length;
        for(int sz=1;sz<len;sz*=2){//每次合并的大小都要不断翻倍
            for(int lo=0;lo<len-sz;lo+=sz+sz){//为什么lo<len-sz,因为最后只要合并到前一个sz
                //对于每个sz都要从头到尾都合并
                merge(a,lo,lo+sz-1,Math.min(lo+sz+sz-1,len-1));
                //注意这里中间节点是lo+sz-1,尾节点为了反正最后长度超过len-1,将尾尾节点定义为最小值
            }
        }
    }




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值