• 常见的排序算法


    1. 冒泡排序

    public interface Sort<T  extends Comparable<T>> {
    
    	public void sort(T[] array);
    }

    /**
     * 
     * 类名: MPSort.java
     * 类描述: 冒泡排序
     * 备注: 
     * <li>比较相邻的元素。如果第一个比第二个大,就交换他们两个。</li>  
     * <li>对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。</li>  
     * <li>针对所有的元素重复以上的步骤,除了最后一个。</li>  
     * <li>持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。</li>  
     */  
    public class MPSort<T extends Comparable<T>> implements Sort<T>{
    
    	@Override
    	public void sort(T[] array) {
    		if(null != array && array.length > 0){
    			for(int i=0; i<array.length-1; i++){
    				for(int j=i+1; j<array.length; j++){
    					if(array[i].compareTo(array[j])>0){
    						T temp = array[i];
    						array[i] = array[j];
    						array[j] = temp;
    					}
    				}
    			}
    		}
    	}
    }

    2. 选择排序

    /**
     * 
     * <pre>
     * 类名: XZSort.java
     * 类描述: 选择排序
     * 备注: 选择排序,先将第一个数和后续的数依次比较,找到最大的(或最小的)数,然后把该数和第一个数位置交换,然后依次对后续的数循环做此处理。
     * </pre>
     */
    public class XZSort<T extends Comparable<T>> implements Sort<T>{
    
    	@Override
    	public void sort(T[] array) {
    		if(null != array && array.length > 0){
    			for(int i=0; i<array.length-1; i++){
    				int index = i;
    				for(int j=i+1; j<array.length; j++){
    					if(array[index].compareTo(array[j]) > 0){
    						index = j;
    					}
    				}
    				if(index != i){
    					T temp = array[i];
    					array[i] = array[index];
    					array[index] = temp;
    				}
    			}
    		}
    	}
    }

    3. 插入排序

    /**
     * 
     * <pre>
     * 类名: CRSort.java
     * 类描述: 插入排序
     * 备注:插入排序把要排序的数组分成两部分,第一部分包含这个数组的所有元素,最后一个元素除外,而第二部分只包含这一元素;
     * 在第一部分排序后,再把这个最后元素插入到此刻已经排好序的第一部分的正确位置。
     * </pre>
     */
    public class CRSort<T extends Comparable<T>> implements Sort<T> {
    
    	@Override
    	public void sort(T[] array) {
    		if(null != array && array.length > 0){
    			for(int i = 1; i< array.length; i++){
    				for(int j = i; j > 0; j--){
    					if(array[j].compareTo(array[j-1]) < 0){
    						T temp = array[j-1];
    						array[j-1] = array[j];
    						array[j] = temp;
    					}
    				}
    			}
    		}
    	}
    }

    4. 快速排序

    /**
     * <pre>
     * 类名: KSSort.java
     * 类描述: 快速排序
     * 备注:  
     * <li>从数列中挑出一个元素,称为“基准”</li>  
     * <li>重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割之后,  该基准是它的最后位置。这个称为分割(partition)操作。</li>  
     * <li>递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li>  
     * </pre>
     */
    public class KSSort<T extends Comparable<T>> {
    
    	public void sort(T[] array, int start, int end) {
    		int i=start; 
    		int j=end;
    		T temp;
    		T p = array[start];
    		do{
    			while(array[i].compareTo(p)<0 && i<end){
    				i++;
    			}
    			while(array[j].compareTo(p)>0 && j>start){
    				j--;
    			}
    			if(i<=j){
    				temp = array[i];
    				array[i] = array[j];
    				array[j] = temp;
    				i++;
    				j--;
    			}
    		}while(i<=j);
    		if(start<j){
    			sort(array, start, j);
    		}
    		if(i<end){
    			sort(array, i, end);
    		}
    	}
    }


    5. 归并排序(转自:http://blog.csdn.net/apei830/article/details/6591632

    /**
     * 项目名: sort
     * 类名: GBSort.java
     * 类描述: 归并排序
     * 备注: 归并排序是把已经排好序的两个序列合并成一个有序序列
     */
    public class GBSort{
    
    	public static void mergeSort(Integer[] data) {  
            sort(data, 0, data.length - 1);  
        }  
      
        public static void sort(Integer[] data, int left, int right) {  
            if (left >= right)  
                return;  
            // 找出中间索引  
            int center = (left + right) / 2;  
            // 对左边数组进行递归  
            sort(data, left, center);  
            // 对右边数组进行递归  
            sort(data, center + 1, right);  
            // 合并  
            merge(data, left, center, right);  
        }  
      
        /** 
         * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序 
         *  
         * @param data 
         *            数组对象 
         * @param left 
         *            左数组的第一个元素的索引 
         * @param center 
         *            左数组的最后一个元素的索引,center+1是右数组第一个元素的索引 
         * @param right 
         *            右数组最后一个元素的索引 
         */  
        public static void merge(Integer[] data, int left, int center, int right) {  
            // 临时数组  
            int[] tmpArr = new int[data.length];  
            // 右数组第一个元素索引  
            int mid = center + 1;  
            // third 记录临时数组的索引  
            int third = left;  
            // 缓存左数组第一个元素的索引  
            int tmp = left;  
            while (left <= center && mid <= right) {  
                // 从两个数组中取出最小的放入临时数组  
                if (data[left] <= data[mid]) {  
                    tmpArr[third++] = data[left++];  
                } else {  
                    tmpArr[third++] = data[mid++];  
                }  
            }  
            // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)  
            while (mid <= right) {  
                tmpArr[third++] = data[mid++];  
            }  
            while (left <= center) {  
                tmpArr[third++] = data[left++];  
            }  
            // 将临时数组中的内容拷贝回原数组中  
            // (原left-right范围的内容被复制回原数组)  
            while (tmp <= right) {  
                data[tmp] = tmpArr[tmp++];  
            }  
        }  
    }

    这几种排序的效率比较:

    public class Test {
    
    	static Random random = new Random(System.nanoTime());
    	
    	public static Integer[] getIngegerArray(int count){
    		Integer[] array = new Integer[count];
    		for(int i=0; i<count; i++){
    			array[i] = random.nextInt(count)+1;
    		}
    		return array;
    	}
    	
    	public static void main(String[] args) {
    		int count = 100000;
    		Integer[] array = getIngegerArray(count);
    		Integer[] array1 = new Integer[count];
    		System.arraycopy(array, 0, array1, 0, count);
    		Integer[] array2 = new Integer[count];
    		System.arraycopy(array, 0, array2, 0, count);
    		Integer[] array3 = new Integer[count];
    		System.arraycopy(array, 0, array3, 0, count);
    		Integer[] array4 = new Integer[count];
    		System.arraycopy(array, 0, array4, 0, count);
    		
    		KSSort ksSort = new KSSort();
    		long time1 = System.nanoTime(); 
    		ksSort.sort(array1, 0, count-1);
    		long time2 = System.nanoTime();
    		System.out.println("快速排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");
    		
    		Sort crSort = new CRSort<>();
    		time1 = System.nanoTime(); 
    		crSort.sort(array2);
    		time2 = System.nanoTime();
    		System.out.println("插入排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");
    		
    		Sort mpSort = new MPSort<>();
    		time1 = System.nanoTime(); 
    		mpSort.sort(array3);
    		time2 = System.nanoTime();
    		System.out.println("冒泡排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");
    		
    		Sort xzSort = new XZSort<>();
    		time1 = System.nanoTime(); 
    		xzSort.sort(array);
    		time2 = System.nanoTime();
    		System.out.println("选择排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");
    <span style="white-space:pre">		</span>GBSort gbSort = new GBSort();
    <span style="white-space:pre">		</span>time1 = System.nanoTime(); 
    <span style="white-space:pre">		</span>gbSort.mergeSort(array6);
    <span style="white-space:pre">		</span>time2 = System.nanoTime();
    <span style="white-space:pre">		</span>System.out.println("归并排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");
    	}
    }


    测试结果1:

    快速排序:排10000个整数耗时:3ms
    插入排序:排10000个整数耗时:681ms
    冒泡排序:排10000个整数耗时:747ms
    选择排序:排10000个整数耗时:486ms

    测试结果2:

    快速排序:排1000个整数耗时:2ms
    插入排序:排1000个整数耗时:7ms
    冒泡排序:排1000个整数耗时:7ms
    选择排序:排1000个整数耗时:5ms
    

    测试结果3:

    快速排序:排50000个整数耗时:20ms
    插入排序:排50000个整数耗时:19009ms
    冒泡排序:排50000个整数耗时:27390ms
    选择排序:排50000个整数耗时:15217ms


    测试结果4:

    快速排序:排10000个整数耗时:3ms
    插入排序:排10000个整数耗时:590ms
    冒泡排序:排10000个整数耗时:665ms
    选择排序:排10000个整数耗时:400ms
    数组自带Api排序:排10000个整数耗时:5ms
    归并排序:排10000个整数耗时:265ms

    另外,再加上一个数组自带的排序方法:

    time1 = System.nanoTime(); 
    Arrays.sort(array5);
    time2 = System.nanoTime();
    System.out.println("数组自带Api排序:排"+count+"个整数耗时:"+(time2-time1)/1000000+"ms");

    输出结果:

    数组自带Api排序:排50000个整数耗时:21ms



  • 相关阅读:
    選定下拉列表的方法
    JAVA学习路线
    封装
    重写(Overriding)
    java内存泄露
    学习实例.文章管理.文章类.Article.java
    方法重载
    学习实例.文章管理.分页查询类.Page.java
    学习实例.文章管理.目标与经验总结
    Java多线程1
  • 原文地址:https://www.cnblogs.com/marcotan/p/4256874.html
Copyright © 2020-2023  润新知