思想:引入的原因:虽然随机选取枢轴时,减少出现不好分割的几率,但是还是最坏情况下还是O(n^2),要缓解这种情况,就引入了三数取中选取枢轴
分析:最佳的划分是将待排序的序列分成等长的子序列,最佳的状态我们可以使用序列的中间的值,也就是第N/2个数。可是,这很难算出来,并且会明显减慢快速排序的速度。这样的中值的估计可以通过随机选取三个元素并用它们的中值作为枢纽元而得到。事实上,随机性并没有多大的帮助,因此一般的做法是使用左端、右端和中心位置上的三个元素的中值作为枢纽元。显然使用三数中值分割法消除了预排序输入的不好情形,并且减少快排大约14%的比较次数
举例:待排序序列为:8 1 4 9 6 3 5 2 7 0
左边为:8,右边为0,中间为6.
我们这里取三个数排序后,中间那个数作为枢轴,则枢轴为6
注意:在选取中轴值时,可以从由左中右三个中选取扩大到五个元素中或者更多元素中选取,一般的,会有(2t+1)平均分区法(median-of-(2t+1),三平均分区法英文为median-of-three)。
具体思想:对待排序序列中low、mid、high三个位置上数据进行排序,取他们中间的那个数据作为枢轴,并用0下标元素存储枢轴。
即:采用三数取中,并用0下标元素存储枢轴。
/**
* @Author 《BoYou》
* @Description 三分取中法 快排
* @Date 2019/1/10 0010
*/
public class Fastsort04 {
public static void main(String[] args) {
Random ran=new Random();
int[] array=new int[100];
for (int i = 0; i <100 ; i++) {
array[i] = ran.nextInt(100)+1;
}
quicksort(array);
System.out.println(Arrays.toString(array));
}
public static void quicksort(int[] array){
quick(array,0,array.length-1);
}
public static void quick(int[] array,int low,int high){
midThree(array,low,high);
int par=partion(array,low,high);
if (par>low+1){
quick(array,low,par-1);
}
if (par<high-1){
quick(array,par+1,high);
}
}
/*
*功能描述
* @author 《Boyou》
* @Date 下午 8:36 2019/1/10 0010
* @param [array, low, high]
* @return void
* 原理 中左右
* 即:array[mid]<=array[low]<=array[high]
*/
public static void midThree(int[] array,int low,int high){
int mid=(low+high)/2;
/* if (array[mid]>array[low]){
swap(array,low,mid);
}
if (array[mid]>array[high]){
swap(array,mid,high);
}
if (array[low]>array[high]){
swap(array,low,high);
}*/
if(array[low]<array[mid]){
swap(array,low,mid);
}
if(array[low]>array[high]){
swap(array,low,high);
}
if(array[mid]>array[high]){
swap(array,mid,high);
}
}
public static void swap(int[] array ,int low,int rand){
int tmp=array[low];
array[low]=array[rand];
array[rand]=tmp;
}
public static int partion(int[] array,int low,int high){
int tmp=array[low];
while (low<high){
while (low<high&&tmp<array[high]){
high--;
}
if (low<high){
array[low]=array[high];
low++;
}else break;
while (low<high&&tmp>array[low]){
low++;
}
if (low<high){
array[high]=array[low];
high--;
}else break;
}
array[low]=tmp;
return low;
}
}