package com.prince.algorithm;
public class QuickSort {
public static void sort(Comparable[] a) {
//使用shuffle消除对输入的依赖
}
private static void sort(Comparable[] a,int low,int high) {
if(high<=low)return;
int j = partition(a,low,high); // 先切分
sort(a,low,j-1); //左部分排序
sort(a,j,high); //右部分排序
}
/**
* 三向切分的快速排序,处理多重复元素的数组
* 从左到右遍历数组一次,维护一个指针lt使得a[low..lt-1]中的元素都小于v,
* 一个指针gt使得a[gt+1..high]中的元素都大于v,一个指针i使得a[lt..i-1]中
* 元素都等于v,a[i..gt]中的元素未确定
* a[i]小于v,将a[lt]和a[i]交换,将lt和i加1;
*a[i]大于v,将a[gt]和a[i]交换,将gt减1;
*a[i]等于v,将i加1;
* @param a
* @param low
* @param high
*/
private static void sort3way(Comparable[] a,int low,int high) {
if(high<=low) return;
int lt = low, i = low+1, gt = high;
Comparable v = a[low];
while(i<=gt)
{
int cmp = a[i].compareTo(v);
if(cmp<0) exch(a,lt++,i++);
else if(cmp>0) exch(a,i,gt--);
else i++;
} //现在a[low..lt-1]<v=a[lt..gt]<a[gt+1..high]
sort(a,low,lt-1);
sort(a,gt+1,high);
}
/**
* 先随意地取a[low]作为切分元素,即那个将会被排定的元素,然后我们从
* 数组的左端开始向右扫描直到找到一个大于等于它的元素,再从数组的右端
* 开始向左扫描直到找到一个大于等于它的元素。然后交换位置。重复下去,
* 我们就可以保证左指针i的左侧元素都不大于切分元素,右指针j的右侧元素都
* 不小于切分元素。当两个指针相遇时,我们只需要将切分元素a[low]和左子
* 数组最右侧的元素a[j]交换然后返回j即可
* 循环中a[i]小于v时我们增大i,a[j]大于v时我们减小j,然后交换
* a[i]和a[j]来保证i左侧的元素都不大于v,j右侧的元素都不小于v
* @param a
* @param low
* @param high
* @return
*/
private static int partition(Comparable[] a,int low,int high) {
int i = low, j = high+1; //左右扫描元素
Comparable v = a[low];
while(true) {
//扫描左右,检查扫描是否结束并交换元素
while(less(a[++i],v)) if(i==high)break;
while(less(v,a[--j])) if(j==low)break;
if(i>=j)break;
exch(a,i,j);
}
exch(a,low,j); //将v=a[j]放入正确的位置
return j;
}
private static boolean less(Comparable v,Comparable w) {
return v.compareTo(w)<0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
private static void show(Comparable[] a) {
//在单行中打印数组
for(Comparable temp:a) {
System.out.println(temp);
}
}
public static boolean isSorted(Comparable[] a){
for(int i=1;i<a.length;i++)
if(less(a[i],a[i-1])) return false;
return true;
}
public static void main(String[] args) {
String[] a = {"aa","ab","dd","ad","abc"};
sort(a);
assert isSorted(a);
show(a);
}
}