最常用的排序——快速排序
一、算法思想
快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止。相比冒泡排序,快速排序每次交换是跳跃式的。每次排序时设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。
二、算法描述
把一列数的第一个数作为基准数,分别从初始序列两端开始探测每次从右往左找比基准数小的数,从左往右找比基准数大的数,将两者交换,交换后继续移动。直到两个指针(i,j)到达同一个数字上(每次j先出发,即每次先从右往左探测,i不可以越过j),将相遇位置的数字与基准数交换。接下来,以第一个基准数分为两个序列,以上面的方法排序,循此往复。
这里写的比较简单,如果需要深入了解,建议还是找一些带图的算法详解。这个算法中最关键的一点是,每次必须先从右向左扫描比基准数小的数,即必须先做j--。
三、实现代码
问题描述:将n个数进行排序。
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 // TODO Auto-generated method stub 6 Scanner reader = new Scanner(System.in); 7 int n = reader.nextInt(); 8 int a[] = new int[n]; 9 for(int i=0;i<n;i++){ 10 a[i]=reader.nextInt(); 11 } 12 QuickSort(0,n-1,a); 13 for(int i=0;i<n;i++){ 14 System.out.printf("%d ",a[i]); 15 } 16 } 17 18 private static void QuickSort(int left, int right, int[] a) { 19 // TODO Auto-generated method stub 20 int i,j,t,temp; 21 if(left>right) 22 return; 23 24 temp=a[left];//基准数 25 i=left; 26 j=right; 27 28 while(i!=j){ 29 //从右往左扫描 30 while(a[j]>=temp&&i<j) 31 j--; 32 //从左往右扫描 33 while(a[i]<=temp&&i<j) 34 i++; 35 //交换 36 if(i<j){ 37 t=a[i]; 38 a[i]=a[j]; 39 a[j]=t; 40 } 41 } 42 a[left]=a[i]; 43 a[i]=temp; 44 45 //递归 46 QuickSort(left,i-1,a); 47 QuickSort(i+1,right,a); 48 } 49 }
四、算法优缺点
快速排序之所以比较快,是因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大得多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的,都是O(N^2),它的平均时间复杂度为O (NlogN)。