Eason-S

导航

排序算法3——快速排序

算法复杂度:O(nlogn)

原理

对于一组给定的记录,通过一趟排序后,将原序列分为两部分,其中一部分的所有记录均比后一部分的所有记录小,然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中的所有记录均有序为止。

程序

 1 public class quicksort {
 2 
 3     public static void quickSort(int array[],int low,int high){
 4         int pivot;
 5         if(low<high){
 6             pivot = partition(array,low,high);
 7             quickSort(array,low,pivot-1);
 8             quickSort(array,pivot+1,high);
 9         }
10     }
11 
12 
13     public static int partition(int array[],int low,int high){
14         int index = array[low];
15         while(low<high){
16             while(low<high&&array[high]>=index)
17                 high--;
18             array[low] = array[high];
19             while(low<high&&array[low]<index)
20                 low++;
21             array[high] = array[low];
22         }
23         array[low] = index;
24         return low;
25     }
26     
27 
28     public static void main(String[] args){
29         int a[] = {5,4,9,8,7,6,0,1,3,2};
30         int len = a.length;
31         quickSort(a,0,len-1);
32         for(int i=0;i<len;i++){
33             System.out.println(a[i]+" ");
34         }
35     }
36 
37 }

优化

1.优化选取枢轴

  采取三数取中法。取三个关键字先进性排序,将中间数作为枢轴,一般是取左端、右端和中间三个数,也可以随机选取。这样至少这个中间数一定不会是最小或最大的数,从概率来说,取三个数均为最小或最大数的可能性微乎其微,因此中间数位于较为中间的值的肯能行就大大提高了。

将上面程序中的第14行改为如下程序

 1 int index;
 2 int m = low + (high - low) / 2;        //中间元素下标
 3 if(array[low]>array[high])
 4     swap(array,low,high);            //交换左端与右端数据,保证左端较小。
 5 if(array[m]>array[high])
 6     swap(array,m,high);                //交换中间与右端数据,保证中间较小。
 7 if(array[m]>array[low])
 8     swap(array,low,m);                //交换中间与左端数据,保证左端较小。
 9 /*此时array[low]已经是整个序列左中右三个关键字中的中间值。*/
10 index = array[low];

2.优化小数组时的排序方案

  当数组非常小时,快速排序反而不如直接插入排序来得更好。我们可以设置一个数组长度阈值(有资料认为7比较合适,也有认为50更合适,实际应用可适当调整),当数组长度在设定阈值之下时,就用直接插入排序,否则用快速排序。

3.优化递归操作

  我们知道递归对性能是有一定的影响的,quickSort方法在其尾部有两次递归操作,如果待排序的序列划分极不平衡,递归深度将趋于n,这就不仅仅是速度快慢的问题了。栈的大小是很有限的,每次递归都会耗费一定的栈空间,函数的参数越多,每次递归耗费的空间也越多。如果能减少递归,将会大大提高性能。

我们采取尾递归优化。

将程序中的5-9行改为如下程序

1 while(low<high){
2     pivot = partition(array,low,high);
3     quickSort(array,low,pivot-1);
4     low = pivot+1;
5 }

 

常见排序算法的特点和比较

排序法   平均时间     最好情形      最差情形 稳定度 额外空间 备注
冒泡  O(n2) O(n)   O(n2)  稳定 O(1) n小时较好
选择  O(n2) O(n2)  O(n2) 不稳定 O(1) n小时较好
插入  O(n2) O(n)  O(n2) 稳定 O(1) 大部分已排序时较好
Shell O(nlogn) O(n1.3) O(ns) 1<s<2 不稳定 O(1) s是所选分组
O(nlogn) O(nlogn) O(nlogn) 不稳定 O(1) n大时较好
归并 O(nlogn) O(nlogn) O(nlogn) 稳定 O(n) n大时较好
快速 O(nlogn) O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好

posted on 2016-05-13 18:03  Eason_S  阅读(596)  评论(0编辑  收藏  举报