简介(先来段废话O(∩_∩)O)
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:(1)通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小;(2)然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。算法描述
(一) 我们先来看算法思想的第一部分---划分
给出一个未排序的数组,我们挑出一个主元(随便一个数),使得数组左右的数小于主元,数组右边的数大于主元,这就是划分的思想,具体的算法实现我们通过例子来讲解。
还是例子来的更直观,如数组a[n]={6,1,2,7,9 ,3,4,5,10,8}
low hight
6 1 2 7 9 3 4 5 10 8
算法描述:(1)挑选第一个元素6为主元(为了方便)
(2)从 hight开始往左移动 hight--,直到a[ hight]<主元(就是6)
(3)hight先停下,轮到low向右移动low++,直到a[low]>主元 low停下 ,交换a[low和a[hight]
(4)a[hight]继续左移重复 (2),(3)步骤 直到low=hight 交换a[hight]和主元,算法结束 。
下面请看过程==================》
a. 从 hight开始往左移动 hight--,一直到a[7]=5时候发现 a[7]<6, hight停止,轮到low向右移动,移动到 a[3]=7>6 ,交换5和7。
low hight
6 1 2 5 9 3 4 7 10 8
b. hight 继续左移,一直到a[6]=4 发现 a[6]<6,hight停止,low向右移,在9停止,交换9和4。
low hight
6 1 2 5 4 3 9 7 10 8
c. hight 继续左移,到3停止,low右移,在3的地方 low==hight,交换6和3,算法停止。
low=hight
3 1 2 5 4 6 9 7 10 8
这就是划分的过程,我们挑选的主元6左边的数据小于6,右边的数大于6(二) 再来看算法思想的第二部分---排序
有了划分,排序就很简单了,我们运用递归,不断的对主元两边的数组划分,通过递归划分就可以对整个数组序。
算法分析
那么快速排序的平均时间复杂度是多少呢?划分部分很明显是O(n)。
根据递归,总的排序平均时间复杂度 T(n) =2T(2/n)+O(n) = O(nlgn) 。
为什么等于O(nlgn) ?建议不懂的读者可以去看看根据递归公式求时间复杂度的资料,算法导论有很详细的数学方法求导,本文暂不讨轮。代码实现
/**
* 快速排序
* */
public class Quicksort {
public Quicksort() {
// TODO Auto-generated constructor stub
}
//
/**
* 划分步骤:a[n]
* (1)6 1 2 7 9 3 4 5 10 8 挑选第一个元素6为主元(为了方便)
* i j
* (2)从j开始往左移动j--,直到a[j]<主元(就是6)
* (3)j先停下,轮到i向右移动i++,直到a[i]>主元 i停下 ,交换a[i]和a[j]
* (4)a[j]继续左移重复 (2),(3)步骤 直到i==j 交换a[j]和主元a[0]算法结束
*
* */
public static int partition(int[] arry,int low,int hight){
int pivotIndex =low;
int pivot = arry[pivotIndex];//主元
int temp = 0;
while(hight!=low){
if(arry[hight]<pivot){
//hight stop,low move
while(arry[low]<=pivot&&low<hight){
low++;
}
if(low<hight){
//交换交换a[low]和a[hight]
temp = arry[low];
arry[low] = arry[hight];
arry[hight] = temp;
}
}else{
hight--;
}
}
//交换a[hight]和主元a[0]
temp = arry[hight];
arry[hight] = pivot;
arry[pivotIndex] = temp;
return hight;
}
//排序
public static void sort(int[] arry,int low,int hight){
if(low<hight){
int pivotIndex = partition(arry,low,hight);
sort(arry,low,pivotIndex);
sort(arry,pivotIndex+1,hight);
}
}
//测试
public static void main(String[] args) {
int[] arry = {6,1,2,7,6,3,4,5,10,8};
sort(arry,0,arry.length-1);
for(int n:arry){
System.out.println(n);
}
}
}
思考
经过上面分析我们知道平均时间复杂度为O(nlgn),那么最坏情况时间复杂度是多少呢?什么样的情况下快速排序是最坏情况,大家可以思考一下。下一篇文章会继续分析。排序之快速排序2已经发表,可点击查看。