算法筆記4:快速排序

標準快速排序

import edu.princeton.cs.algs4.StdRandom;
/**
 * 標準快速排序
 * @author XY
 *
 */
@SuppressWarnings("rawtypes")
public class QuickSort {
	
	public static void sort(Comparable[] v){
		StdRandom.shuffle(v);//隨機打亂數組
		int N=v.length;
		sort(v, 0, N-1);
	}
	public static void sort(Comparable[] v,int lo,int hi){
		if(lo>=hi) return;
		int j=position(v, lo, hi);//找到切分點,切分點的位置已經排定
		sort(v, lo, j-1);
		sort(v, j+1, hi);		
	}
	private static int position(Comparable[] v,int lo,int hi){
		//找到切分位置j,保證j的左邊小於等於v[lo],右邊大於等於v[lo]
		int i=lo;
		int j=hi+1;
		Comparable low=v[lo];
		while(true){
			while(less(v[++i], low)) if(i==hi) break;
			//從左到右遇到的不小於v[lo]的元素
			while(less(low, v[--j])) if(j==lo) break;
			//從右到左遇到的不大於v[lo]的元素
			if (j>i) {//左右指針還未相遇,交換
				Comparable temp=v[i];
				v[i]=v[j];
				v[j]=temp;
			} else  break;				
			
		}
		v[lo]=v[j];
		v[j]=low;//交換v[j]和v[lo],v[i]>=v[lo],v[j]<=v[lo],所以選擇j爲切分位置
		return j;
	}
	public static boolean less(Comparable a, Comparable b) {
		return a.compareTo(b) < 0;
	}
	
	public static boolean issorted(Comparable[] v) {
		for (int i = 0; i < v.length - 1; i++) {
			if (less(v[i + 1], v[i]))
				return false;
		}
		return true;
	}
	public static void show(Comparable[] v){
		StringBuffer sb=new StringBuffer();
		for (int i = 0; i < v.length; i++) {
			sb.append(" "+v[i]);
		}
		System.out.println(sb.toString());
	}
	public static void main(String[] args){
		Double[] n={1.2,3.5,8.2,0.5,1.8,2.9,3.0,4.5,0.3,0.1,5.3,2.9,4.2,8.0,7.6};
		sort(n);
		show(n);
		System.out.println(issorted(n));
	}

}

三取樣切分和小段插入排序的快速排序

爲了使得每次切分的位置儘可能的接近N/2,使用隨機三個數的中位數。在數組長度小於10時使用插入排序。

import edu.princeton.cs.algs4.StdRandom;
/**
 * 使用三取樣中位數和小段插入排序的快速排序
 * @author XY
 *
 */
@SuppressWarnings("rawtypes")
public class QuickSortB {
	public static void sort(Comparable[] v){
		StdRandom.shuffle(v);
		int N=v.length;
		sort(v, 0, N-1);
	}
	private static void sort(Comparable[] v,int lo,int hi){
		if(hi-lo<10){//快速排序的切換值一般在5-15之間
			InsertSort.sort(v, lo, hi);	return; 	}
		int mid=mid(v, lo, lo+(hi-lo)/2, hi);//找到隨機三個數的中位數作爲v[lo]
		exchange(v, lo, mid);
		int j=position(v, lo, hi);
		sort(v, lo, j-1);
		sort(v, j+1, hi);
		
	}
	public static int mid(Comparable[] v,int i,int j,int k){
		
		int a=v[j].compareTo(v[i]);
		int b=v[j].compareTo(v[k]);
		int c=v[i].compareTo(v[k]);
		if(a*b<0) return j;
		if(b*c>0) return i;		
		return k;
	}
	
	private static int position(Comparable[] v,int lo,int hi){
		int i=lo;
		int j=hi+1;
		Comparable low=v[lo];
		while(true){
			while(less(v[++i], low)) {if(i==hi) break;}
			while(less(low, v[--j])) {}
			if (j>i) {
				Comparable temp=v[i];
				v[i]=v[j];
				v[j]=temp;
			} else  break;				
			
		}
		v[lo]=v[j];
		v[j]=low;
		
		return j;
	}
	public static boolean less(Comparable a, Comparable b) {
		return a.compareTo(b) < 0;
	}

	public static void exchange(Comparable[] v, int a, int b) {
		Comparable w = v[a];
		v[a] = v[b];
		v[b] = w;
	}
	
	public static boolean issorted(Comparable[] v) {
		for (int i = 0; i < v.length - 1; i++) {
			if (less(v[i + 1], v[i]))
				return false;
		}
		return true;
	}
	public static void show(Comparable[] v){
		StringBuffer sb=new StringBuffer();
		for (int i = 0; i < v.length; i++) {
			sb.append(" "+v[i]);
		}
		System.out.println(sb.toString());
	}
	public static void main(String[] args){
		Double[] n={1.2,3.5,8.2,0.5,1.8,2.9,3.0,4.5,0.3,0.1,5.3,2.9,4.2,8.0,7.6};
		
		sort(n);
		show(n);
		System.out.println(issorted(n));
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章