package demo;
import java.util.Arrays;
public class P33 {
//快速排序属于分治法的一种。
//思路:分解时确保主元左边都小于等于主元、右边都大于主元。然后递归地对左边、右边再进行排序。最后结果不用再合并。
public static void main(String[] args) {
int[] arr= {10,16,4,5,25,13,20};
quickSort(arr, 0, 6);
System.out.println(Arrays.toString(arr));
}
static void quickSort(int[] arr,int p,int r) {
if(p<r) {
//int q=partition(arr,p,r);
int q=partition2(arr,p,r);
quickSort(arr, p, q-1);
quickSort(arr, q+1, r);
}
}
static int partition(int[] arr,int p,int r) { //单向扫描
//优化,三点中值法,取头、中、尾三点的中值作为主元
int mid=p+((r-p)>>1);
int midValue; //中值的下标
int temp;
if( (arr[mid]-arr[p])*(arr[mid]-arr[r])<0 ) {
midValue=mid;
}
else if( (arr[p]-arr[mid])*(arr[p]-arr[r])<0 ) {
midValue=p;
}
else {
midValue=r;
}
temp=arr[p]; //把中值交换到主元位置
arr[p]=arr[midValue];
arr[midValue]=temp;
int value=arr[p]; //把p作为主元
int left=p+1;
int right=r;
while(left<=right) { //左右交错为结束条件,此时右指针指向左区末尾,左指针指向右区开头
if(arr[left]<=value) { //小于等于,则左指针右移
left++;
}
else { //大于,则左、右指针交换值,右指针左移
temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
right--;
}
}
arr[p]=arr[right];
arr[right]=value;
return right;
}
static int partition2(int[] arr,int p,int r) { //双向扫描
//优化,三点中值法,取头、中、尾三点的中值作为主元
int mid=p+((r-p)>>1);
int midValue; //中值的下标
int temp;
if( (arr[mid]-arr[p])*(arr[mid]-arr[r])<0 ) {
midValue=mid;
}
else if( (arr[p]-arr[mid])*(arr[p]-arr[r])<0 ) {
midValue=p;
}
else {
midValue=r;
}
temp=arr[p]; //把中值交换到主元位置
arr[p]=arr[midValue];
arr[midValue]=temp;
int value=arr[p]; //把p作为主元
int left=p+1;
int right=r;
while(left<=right) { //左右交错为结束条件,此时右指针指向左区末尾,左指针指向右区开头
while(left<=right && arr[left]<=value) left++; //让左指针指向第一个大于主元的元素
while (left <= right && arr[right] > value)
right--; // 让右指针指向 从右边数第一个 小于等于主元的元素
if (left < right) { //交换值
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
arr[p]=arr[right];
arr[right]=value;
return right;
}
}