標準快速排序
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));
}
}