3.归并排序Java实现及优化

public class MergeSort {

	/**
	 * 归并排序,归并array[l,r]
	 * @param array
	 * @param l
	 * @param r
	 */
	public static void mergeSort(int array[] ,int l,int r){
		if(l>=r){
			return ;
		}
		int mid = (l+r)/2;
		//双路归并
		mergeSort(array, l, mid);
		mergeSort(array, mid+1, r);
		//归并,使array[l,mid]与array[mid+1,r]两部分合并为一个有序的数组:array[l,r]
		merge(array,l,mid,r);
	}

	/**
	 * 合并有序数组array[l,mid]与array[mid+1,r]为一个有序的数组:array[l,r]
	 * @param array
	 * @param l
	 * @param mid
	 * @param r
	 */
	private static void merge(int[] array, int l, int mid, int r) {
		//暂存待合并的数组aux[0,r]=array[l,r];
		int[] aux = Arrays.copyOfRange(array, l, r+1);
		int i=l,j=mid+1;//两个有序数组的起始值分别为i,j
		//对array的[l,r]重新赋值,形成有序数组
		for(int k=l;k<=r;k++){
			//第一个有序数组的元素已经全部在array里排好,将第二个数组的元素全部依次赋值
			if(i>mid){
				array[k]=aux[j-l];j++;
			}else if(j>r){//第二个有序数组array[mid+1,r]的元素已经全部在array里排好,将第一个数组的元素全部依次赋值
				array[k]=aux[i-l];i++;
			}else if(aux[i-l]<aux[j-l]){//将两个有序数组中小的值重新赋值给对应的array[k]
				array[k]=aux[i-l];i++;
			}else{
				array[k]=aux[j-l];j++;
			}
		}
	}
	
	public static void main(String[] args) {
		int[] array = new int [10];
		for(int i=0;i<10;i++){
			array[i]=(int)(Math.random()*10);
		}
		mergeSort(array, 0, array.length-1);
		System.out.println(Arrays.toString(array));
	}
}

2.优化思路1:在归并两个已经有序的数组的时候,应该先判断arr[l...mid]的最大的元素与arr[mid+1...r]的最小的元素的大小,即判断arr[mid]与arr[mid+1]的大小,前者小于后者这说明两个有序数组不用再归并就已经有序了。

优化思路2:随着归并 的进行,整个数组越来越有序,而插入排序在数组近乎有序的时候几乎可以退化为O(n)级别的排序,所以可以当数组规模小到一定程度的时候,采用插入排序,就可以加快排序速度。

package com.cl.mergesort;

import com.cl.insertsort.InsertionSort;
import com.cl.utils.SortTestHelper;

public class MergeSort {

    public static void sort(Comparable[] arr){

        __mergeSort(arr,0,arr.length-1);
    }

    /**
     * 对arr[l...r]的范围进行排序
     * @param arr
     * @param l
     * @param r
     */
    private static void __mergeSort(Comparable[] arr, int l, int r) {
       /* if(l>=r){//处理的出局为1个或空
            return ;
        }*/
       //优化2:规模只需要处理16个元素
       if(r-l<=15){
           InsertionSort.sort(arr,l,r);
           return ;
       }
        //l+r可能会溢出
        int mid = (l+r)/2;
        __mergeSort(arr,l,mid);
        __mergeSort(arr,mid+1,r);
        //优化1:arr[mid]<arr[mid+1]说明已经有序了,不用再归并
        if(arr[mid].compareTo(arr[mid+1])>0)
            __merge(arr,l,mid,r);
    }

    /**
     * 将arr[l...mid]与arr[mid+1...r]归并
     * @param arr
     * @param l
     * @param mid
     * @param r
     */
    private static void __merge(Comparable[] arr, int l, int mid, int r) {
        Comparable[] aux = new  Comparable[r-l+1];
      /*  for(int i=l;i<=r;i++){
            aux[i-l]=arr[i];
        }*/
        System.arraycopy(arr,l,aux,0,(r-l+1));

        int i=l,j=mid+1;//指向数组开头的位置
        for(int k=l;k<=r;k++){
            if(i>mid){
                arr[k]=aux[j-l];
                j++;
            }
            else if(j>r){
                arr[k]=aux[i-l];
                i++;
            }//索引合法的话
            else if(aux[i-l].compareTo(aux[j-l])<0){
                arr[k]=aux[i-l];
                i++;
            }else{
                arr[k]=aux[j-l];
                j++;
            }
        }
    }

  
    public static void main(String[] args) {
        int n = 50000;
        /*Integer[] arr = SortTestHelper.generateRandomArray(n,0,n);
        Integer[] arr2 = SortTestHelper.copyIntArray(arr);
        SortTestHelper.testSort("com.cl.mergesort.MergeSort",arr);
        SortTestHelper.testSort("com.cl.insertsort.InsertionSort",arr2);
    */
        Integer[] arr = SortTestHelper.generateNearlyOrderedArray(n,10);//产生近乎有序的数组
        Integer[] arr2 = SortTestHelper.copyIntArray(arr);
        SortTestHelper.testSort("com.cl.mergesort.MergeSort",arr);
        SortTestHelper.testSort("com.cl.insertsort.InsertionSort",arr2);

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值