高级排序之快速排序

这一个算是一个比较完善的快速排序了吧,就是代码多了点,没办法,要想性能好,考虑的东西就得多点。

package sort;

public class QuickSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n = 10000000;
		int[] arr = new int[n];
		for (int i = n; i > 0; i--) {
			arr[i - 1] = i;
		}
		QuickSort q = new QuickSort(arr);
		long now = System.currentTimeMillis();
		q.sort();
		System.out.println("time="+(System.currentTimeMillis() - now));
		//q.display();
	}

	private int[] arr;
	
	public QuickSort(int[] arr){
		this.arr = arr;
	}
	
	public void display(){
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
	
	public void sort(){
		recQuickSort(0,arr.length - 1);
	}
	private void recQuickSort(int left,int right){
		int size = right - left + 1;
		if(size < 10){
			//小于10的小数组可以用插入排序,比较省事
			insertSort(left,right);
		}else{
			int maddie = getMiddleValue(left,right);
			//获取最平均的枢纽值
			int partition = partitionIt(left,right,maddie);
			recQuickSort(left,partition - 1);
			recQuickSort(partition + 1,right);
		}
	}
	
	
	/**将指定范围内的数据用枢纽值切割成两个部分,
	 * 枢纽值做为分界,在枢纽值左边的全部小于它,右边全部大于它
	 * @param left 左边索引
	 * @param right 右边索引
	 * @param privot 枢纽值
	 * @return
	 */
	private int partitionIt( int left, int right, int privot) {
		int leftPtr = left;
		int rightPtr = right - 1;
		while(true){
			//左边第二个数据(第一个数据已经在getMiddleValue方法里排好序,肯定比枢纽值小)和枢纽值比较,碰到小于枢纽值的数据停止比较
			while(arr[++leftPtr] < privot);
			//右边第三个数据和枢纽值比较(右边第一个在getMiddleValue方法里排序肯定比枢纽值大,第二个是枢纽值本身,都不用比较)
			while(arr[--rightPtr] > privot);
			//指针交叉停止比较
			if(leftPtr >= rightPtr){
				break;
			}else{
				//将左边小于枢纽值的数据和右边大于枢纽值的数据交换
				swap(leftPtr,rightPtr);
			}
		}
		//将枢纽值放到边界处(此时该枢纽值已经处于最终排序的位置,也就是说它不需要再移动了)
		swap(leftPtr,right - 1);
		return leftPtr;
	}

	/**获取比较平均的枢纽值(这在逆序的情况下很有用)
	 * 分别取最左,中间,最右三个值,取当中的中间值作为枢纽值,并对它们排序
	 * @param left
	 * @param right
	 * @return
	 */
	private int getMiddleValue( int left, int right) {
		int middle = (left + right)/2;
		if(arr[left] > arr[middle])
			swap(left,middle);
		if(arr[left] > arr[right])
			swap(left,right);
		if(arr[middle] > arr[right])
			swap(middle,right);
		//中间值和最右边倒数第二个值交换,这样的话最右边和其左边第一个都不用参加和枢纽值的比较,因为他们是大于等于的。
		swap(middle,right - 1);
		return arr[right - 1];
	}

	/**交换元素
	 * @param a
	 * @param b
	 */
	private void swap(int a,int b){
		int temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}
	
	/**插入排序
	 * @param left
	 * @param right
	 */
	private void insertSort(int left,int right){
		int out,inner,temp;
		for (out = left + 1 ; out < right; out++) {
			 temp = arr[out];
			 inner = out;
			 while(inner > left && arr[inner - 1] >= temp){
				 arr[inner] = arr[inner - 1];
				 inner--;
			 }
			 arr[inner] = temp;
		}
	}
}
 100w逆序排序耗时28毫秒。比希尔快一点哦。付出的是复杂的算法和大量的代码。看如何取舍咯。

你可能感兴趣的:(快速排序)