算法与数据结构基础(四)高级排序算法1.归并排序


一句话概括归并排序算法:通过二分法将一组数据不断分割至最底层一个,然后依次从最底层向上每两组使用归并排序排出来。





归并排序算法步骤分两步(结合上图):1.是不断划分(二分法) 2.不断把划分后的数据一步步归并起来(方法是:先复制得到相同一个数组,建立三个指针,两个在二分的新数组中,一个在原数组里指定接下来要修改的位置,通过比较两指针的数字决定放谁到上面那个指针里)


复杂度:O(n log n)


先展示显示排序算法所需的测试类:

import java.lang.reflect.Method;

public class SortTestHelper {

	public static void testSort(String sortClassName,Comparable[] arry)
	{
		try {
			
			//告诉类名即可获取class对象
			Class sortClass =  Class.forName(sortClassName);
			//指明方法名和参数列表就可以获取
			//getDeclaredMethod()获取的是类自身声明的所有方法,包含public、protected和private方法。	  
			//getMethod()获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。
			Method sortMethod = sortClass.getDeclaredMethod("sort", new Class[]{Comparable[].class});
			Object[] params = new Object[]{arry};
			
			long startTime = System.currentTimeMillis();
			
			//第一个参数是调用哪个对象实例的此方法,静态就写null,第二个为方法参数
			sortMethod.invoke(null, params);
			
			long overTime = System.currentTimeMillis();
			
			System.out.println("耗时:"+(overTime-startTime+" ms!"));
			
			judgeSorted(arry);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void judgeSorted(Comparable[] arry) {
		
		for (int i = 0; i < arry.length-1; i++) {
			if(arry[i].compareTo(arry[i+1])<0)
			{
				System.out.println("排序失败!");
				return;
			}
		}
		System.out.println("排序成功!");
		
	}
	
	public static void print(Object[] data) {
		
		int n = data.length;
		
		for(int i=0;i<n;i++)
		{

			System.out.print(data[i]+"--");
		}
		System.out.println();
	}
	
	public static Integer[] generateRandomArray(int n,int min, int max){
		
		assert min>max;
		
		Integer[] data = new Integer[n];
		
		for (int i = 0; i < data.length; i++) {
			data[i] = new Integer((int)Math.random()*(max-min+1)+min);
		}
		
		return data;
		
	}
	
}


1.版本一:

public class MergeSort {
	
	public static void sort(Comparable[] data,int l,int r){
		
		int mid = (r-l)/2+l;
		
		if(l>=r)
			return;
		
		sort(data,l,mid);
		sort(data,mid+1,r);
		
		MergeSort(data,l,r);
		
	}
	
	public static void sort(Comparable[] data){
		sort(data,0,data.length-1);
	}
	

	private static void MergeSort(Comparable[] data, int l, int r) {
		
		Comparable[] dataCopy = new Comparable[r-l+1];
		
		for (int i = 0; i < dataCopy.length; i++) {
			dataCopy[i] = data[l+i];
			
		}
		
		int mid = (l+r)/2;
		
		int i=l,j=mid+1,k=l;
		
		for (; k < dataCopy.length; k++) {
			
			if(i>mid)
			{
				data[k]=dataCopy[j-l];
				j++;
			}
			else if(j>r){
				data[k]=dataCopy[i-l];
				i++;
			}
			else{
				
				if(dataCopy[i].compareTo(dataCopy[j])==1){
					data[k]=dataCopy[j-l];
					j++;
				}
				else if(dataCopy[i].compareTo(dataCopy[j])==-1){
					data[k]=dataCopy[i-l];
					i++;
				}
				
			}
			
		}
		
		
	}
}

2.优化一:

排序已经有序的数据,会发现插入排序(插入排序这时候会退化为 n 级别)比归并排序快很多。思考得出,可以把最后那个归并前进行if判断,如果arr[mid]>arr[mid+1]时才要进行归并!

public static void sort(Comparable[] data,int l,int r){
		
		int mid = (r-l)/2+l;
		
		if(l>=r)
			return;
		
		sort(data,l,mid);
		sort(data,mid+1,r);
		
		if(data[mid]>data[mid+1])
			MergeSort(data,l,r);
		
	}

3.优化二:当数据比较小的时候使用插入排序较好

public static void sort(Comparable[] data,int l,int r){
		
		int mid = (r-l)/2+l;
		
		if(r-l<15){
                  insertSort(arr,l,r);
		  return;
                }
		
		sort(data,l,mid);
		sort(data,mid+1,r);
		
		if(data[mid]>data[mid+1])
			MergeSort(data,l,r);
		
	}


原文地址:https://www.cnblogs.com/chz-blogs/p/9380980.html