快速排序使用分治法(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); } }