快速排序
1.快速排序
public void quick(int[] arr,int lo,int hi){
if(lo >= hi) return;
int j = partition(arr,lo,hi);
quick(arr,lo,j-1);
quick(arr,j+1,hi);
}
public int partition(int[] arr,int lo,int hi){
int v = arr[lo];
int i = lo, j = hi+1;
while(true){
while(v < arr[--j]);
while(arr[++i] < v) if(i == j) break;
if(i >= j) break;
exch(arr,i,j);
}
exch(arr,lo,j);
return j;
}
2.快速排序简单优化
public void quickMedian(int[] arr,int lo,int hi){
int len = hi-lo+1;
if(len <= 10){
insertion(arr,lo,hi);
return;
}
int j = partitionMedian(arr,lo,hi);
quickMedian(arr,lo,j-1);
quickMedian(arr,j+1,hi);
}
public int partitionMedian(int[] arr,int lo,int hi){
int len = hi-lo+1;
setMedian(arr,lo,hi);
int v = arr[lo];
int i = lo, j = hi+1;
while(true){
while(v < arr[--j]);
while(arr[++i] < v);
if(i >= j) break;
exch(arr,i,j);
}
exch(arr,lo,j);
return j;
}
public void setMedian(int[] arr,int lo,int hi){
int mid = (lo+hi)/2;
int max = lo;
if(arr[max] < arr[mid]) max = mid;
if(arr[max] < arr[hi]) max = hi;
exch(arr,max,hi);
if(arr[lo] < arr[mid]) exch(arr,lo,mid);
}
public void exch(int[] arr,int i,int j){
if(i == j) return;
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public void insertion(int[] arr,int lo,int hi){
for(int i=lo+1;i<=hi;++i)
for(int j=i;j>lo && arr[j]<arr[j-1];--j)
exch(arr,j,j-1);
}
3.快速排序—三向切分
public void quick3Way(int[] arr,int lo,int hi){
if(lo >= hi) return;
int v = arr[lo];
int lt = lo, gt = hi;
for(int i=lo+1;i<=gt;++i){
if (arr[i] < v) exch(arr, lt++, i);
if (arr[i] > v) exch(arr, gt--, i--);
}
quick3Way(arr,lo,lt-1);
quick3Way(arr,gt+1,hi);
}
4.快速三向切分(熵最优)
public void quick3WayPartition(int[] arr,int lo,int hi){
int len = hi-lo+1;
if(len <= 10){
insertion(arr,lo,hi);
return;
}
else if(len <= 40){
int mid = (lo+hi)/2;
int med = median(arr,lo,mid,hi);
exch(arr,lo,med);
}
else{
int sep = len / 8;
int mid = lo + len / 2;
int m1 = median(arr,lo,lo+sep,lo+sep*2);
int m2 = median(arr,mid-sep,mid,mid+sep);
int m3 = median(arr,hi-sep*2,hi-sep,hi);
mid = median(arr,m1,m2,m3);
exch(arr,lo,mid);
}
int v = arr[lo];
int i,j,p,q;
i = p = lo; j = q = hi+1;
while(true){
while(v < arr[--j]);
while(arr[++i] < v) if(i == j) break;
if(i == j) exch(arr,i,++p);
if(i >= j) break;
exch(arr,i,j);
if(arr[i] == v) exch(arr,i,++p);
if(arr[j] == v) exch(arr,j,--q);
}
i = j + 1;
for(int k=lo;k<p;++k) exch(arr,k,j--);
for(int k=hi;k>=q;--k) exch(arr,k,i++);
quick3WayPartition(arr,lo,j);
quick3WayPartition(arr,i,hi);
}
public int median(int[] arr,int lo,int mid,int hi){
return arr[lo]<arr[mid]?(arr[lo]<arr[hi]?(arr[mid]<arr[hi]?mid:hi):lo)
:(arr[lo]>arr[hi]?(arr[mid]<arr[hi]?hi:mid):lo);
}
5.多线程并行快速排序
public class Quick<E> extends RecursiveAction{
private E[] elements;
private Comparator<E> comparator;
private int lo;
private int hi;
public Quick(E[] elements, Comparator<E> comparator) {
this.elements = elements;
this.comparator = comparator;
this.lo = 0;
this.hi = elements.length - 1;
}
public Quick(E[] elements) {
this.elements = elements;
this.comparator = (E x,E y) -> {
if(x instanceof Comparable) return ((Comparable) x).compareTo(y);
else throw new RuntimeException("需要传入Comparator或者实现Comparable");
};
this.lo = 0;
this.hi = elements.length - 1;
}
private Quick(E[] elements,int lo,int hi){
this.elements = elements;
this.lo = lo;
this.hi = hi;
}
public void sort(){ quickMedian(elements,lo,hi); }
public void parallelSort(){
ForkJoinPool forkJoin = (ForkJoinPool) Executors.newWorkStealingPool();
try {
forkJoin.submit(this).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
forkJoin.shutdown();
}
@Override
protected void compute() {
if(hi - lo <= 10000) quickMedian(elements,lo,hi);
else{
int j = partitionMedian(elements,lo,hi);
Quick<E> left = new Quick<>(elements,lo,j-1);
Quick<E> right = new Quick<>(elements,j+1,hi);
invokeAll(left,right);
}
}
private void quickMedian(E[] arr,int lo,int hi){
int len = hi-lo+1;
if(len <= 10){
insertion(arr,lo,hi);
return;
}
int j = partitionMedian(arr,lo,hi);
quickMedian(arr,lo,j-1);
quickMedian(arr,j+1,hi);
}
private int partitionMedian(E[] arr,int lo,int hi){
int len = hi-lo+1;
setMedian(arr,lo,hi);
E v = arr[lo];
int i = lo, j = hi+1;
while(true){
while(((Comparable)v).compareTo(arr[--j]) < 0);
while(((Comparable)arr[++i]).compareTo(v) < 0);
if(i >= j) break;
exch(arr,i,j);
}
exch(arr,lo,j);
return j;
}
private void setMedian(E[] arr,int lo,int hi){
int mid = (lo+hi)/2;
int max = lo;
if(((Comparable)arr[max]).compareTo(arr[mid]) < 0) max = mid;
if(((Comparable)arr[max]).compareTo(arr[hi]) < 0) max = hi;
exch(arr,max,hi);
if(((Comparable)arr[lo]).compareTo(arr[mid]) < 0) exch(arr,lo,mid);
}
private void exch(E[] arr,int i,int j){
if(i == j) return;
E temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private void insertion(E[] arr,int lo,int hi){
for(int i=lo+1;i<=hi;++i)
for(int j=i;j>lo && ((Comparable)arr[j]).compareTo(arr[j-1]) < 0;--j)
exch(arr,j,j-1);
}
}