归并排序(Java)

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and
Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使
子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

在这里插入图片描述
非递归方法:

  1. 将无序数组按一组1个,2个,4个…分 ;使用循环 递增条件为2*n;
  2. 当一组按照一个分时,进行 合并,存放入新的数组,这个过程一直循环到 最后一组为数组的所有值
  3. 将最终合并的数组按照顺序 拷贝给 无序数组

程序实现:


public static void mergeSort(int[] array) {
        for (int gap = 1; gap < array.length; gap*=2) {
            merge1(array,gap);
        }
}
//合并方法
public static void merge1(int[] array,int gap) {
		//新的数组
        int[] tmp = new int[array.length];
        //新数组的下表
        int i = 0;
        
		// 每次分组之后的 无序段下表代表
        int s1 = 0;
        int e1 = s1+gap-1;
        int s2 = e1+1;
        int e2 = (s2+gap-1 >= array.length) ? array.length-1 : s2+gap-1;
        // 这个循环是有两段无序的都存在时
        while (s2 < array.length) {
            while (s1 <= e1 && s2 <= e2) {
                //判断比较,并存入新的数组 
                if(array[s1] <= array[s2]) {
                    tmp[i++] = array[s1++];
                } else {
                    tmp[i++] = array[s2++];
                }
            }
            while(s1 <= e1) {
                tmp[i++] = array[s1++];
            }
            while(s2 <= e2) {
                tmp[i++] = array[s2++];
            }
            //重新s1,e1,s2,e2 位置
            s1 = e2+1;
            e1 = s1+gap-1;
            s2 = e1+1;
            e2 = (s2+gap-1 >= array.length) ? array.length-1 : s2+gap-1;
        }
        //判断s1是否有数据 代表 只有一组无序数据段
        while(s1 < array.length) {
            tmp[i++] = array[s1++];
        }
        //拷贝tmp到array
        for (int j = 0; j < tmp.length; j++) {
            array[j] = tmp[j];
        }   
}

递归版本

  1. 递归方法和二叉树类似, 先一分为二,再一直向左递归,知道递归为 每组一个元素时结束,开始合并;
  2. 合并,比较进行,将较小的放入新的的数组中,两个同时从头开始比较,之后要将较长的数据段之后的所有数据也放入新数组;
  3. 将合并之后的拷贝入新的数组,因为两个合并完就拷贝一次,所以要注意下表;

程序如下:

    public static void mergeSort1(int[] array,int low,int high) {
    	//终止条件
        if(low == high) {
            return;
        }
        int mid = (low+high)/2;
       
        mergeSort1(array,low,mid);
        mergeSort1(array,mid+1,high);
        //合并
        merge(array,low,mid,high);
    }
    public static void merge(int[] array,int low,int mid,int high){
    	//s1 s2 代表 需要合并的两段数据的 最开始下标
        int s1 = low;
        int s2 = mid+1;
        int len = high-low+1; //合并完的数组长度
		//新的数组
        int[] tmp = new int[len];
        int i = 0;       
        while (s1 <= mid && s2 <= high) {
        //进行比较 放入新的数组
            if(array[s1] <= array[s2]) {
                tmp[i++] = array[s1++];
            } else {
                tmp[i++] = array[s2++];
            }
        }

        //判断两个归并段 中 是否还有归并段有数据
        while(s1 <= mid) {
            tmp[i++] = array[s1++];
        }
        while(s2 <= high) {
            tmp[i++] = array[s2++];
        }
        for (int j = 0; j < len; j++) {
            array[low + j] = tmp[j];
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值