常见的排序算法

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



原文地址:https://www.cnblogs.com/marcotan/p/4256874.html