快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分割(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递回的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递回下去,但是这个演算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
import java.util.Arrays;
public class Main{
public static void swap(int[] arr,int i,int j){
int tmp=arr[j];
arr[j]=arr[i];
arr[i]=tmp;
}
public static int partition(int[] arr,int left,int right){
int privotValue=arr[right];
int i=left-1;
for(int j=left;j<=right-1;j++){
if(arr[j]<=privotValue){
i++;
swap(arr,i,j);
}
}
swap(arr,i+1,right);
return i+1;
}
public static int partitionDoubleDirection(int[] arr,int left,int right){
int i=left;
int j=right+1;
int v=arr[left];
while(true){
while(i<=right&&arr[++i]<v){
;
}
while(j>=left&&arr[--j]>v){
;
}
if(i>=j) break;
swap(arr,i,j);
}
swap(arr,left,j);
return j;
}
public static void quicksort(int[] arr,int left,int right){
if(left<right){
//int par=partition(arr,left,right);
int par=partitionDoubleDirection(arr,left,right);
quicksort(arr,left,par-1);
quicksort(arr,par+1,right);
}
}
//三向切分
public static void sort(int[] arr,int left,int right){
if(left>=right){
return;
}
int lt=left;
int gt=right;
int v=arr[left];
int i=left;
while(i<=gt){
if(arr[i]<v){
swap(arr,lt++,i++);
}else if(arr[i]>v){
swap(arr,i,gt--);
}else{
i++;
}
}
sort(arr,left,lt-1);
sort(arr,gt+1,right);
}
public static void isSort(int[] arr){
for(int i=0,j=1;j<arr.length;i++,j++){
if(arr[i]>arr[j]){
System.out.println("排序失败");
System.out.print(Arrays.toString(arr));
return;
}
}
System.out.println("排序成功");
System.out.print(Arrays.toString(arr));
}
public static void main(String[] args){
int[] arr=new int[10000];
for(int i=0;i<10;i++){
arr[i]=(int)(Math.random()*1000);
}
//quicksort(arr,0,arr.length-1);
sort(arr,0,arr.length-1);
isSort(arr);
}
}