zoukankan      html  css  js  c++  java
  • 算法与数据结构基础(四)高级排序算法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);
    		
    	}


  • 相关阅读:
    不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean
    VS2010水晶报表的添加与使用
    使用SelectClipRgn注意事项
    使用SelectClipRgn注意事项
    使用事件CreateEvent注意事项
    【转】Delphi内嵌ASM简易教程
    栈顶和栈底示意图
    【转】对ARM堆栈的理解
    UISegmentedControl的基本使用
    C语言小知识总结
  • 原文地址:https://www.cnblogs.com/chz-blogs/p/9380980.html
Copyright © 2011-2022 走看看