快速排序法
快速排序法相交之前的三种排序法来讲,是一种运行速度较快的排序算法,也是一种大家经常使用的排序算法。
快速排序法使用一种分治的思想,将待排数组切分成两个子数组,将两个子数组进行独自的排序。
与归并排序的区别
快速排序法与归并排序不同,归并排序是将两个有序的子数组分别排序,然后将两个子数组归并后形成一个有序的数组。而快速排序法则是将子数组分别排序后直接就形成了一个有序的数组。还有一个区别是归并排序法是将待排数组等分成两份,而快速排序的切分位置取决于数组本身。
代码
上面的叙述可能有一些抽象,下面列出代码,分析代码过后应该会更容易理解。
代码是用递归的方式实现的快速排序法,将数组的第一个元素作为切分元素。
切分函数
public int partition(int a[] , int lo , int hi){
int i = lo;
int j = hi+1;
int v = a[lo]; //切分元素
while(true){
while(less(a[++i],v))
if(i == hi)
break;
while(less(v,a[--j]))
if(j == lo)
break;
if(i >= j)
break;
exchange(a , j , i);
}
exchange(a , lo , j );
return j;
}
排序函数
protected void sort(int[] a, int lo, int hi) {
// TODO Auto-generated method stub
if(hi <= lo)
return;
int j = partition(a , lo , hi);
sort(a , lo , j-1);
sort(a , j+1 , hi);
}
因为使用递归所以代码量看上去很少,但是递归也相对于来说比较容易出错。
关于时间复杂度
快速排序的最好情况是每次都能讲数组平均分成两部分,时间复杂度约为N*lgN;最坏的情况是每次切分后有一个数组是为空,这是比较次数就是N+(N-1)+(N-2)+....+1 = (N+1)N/2.
快速排序法的平均时间复杂度约为N*lgN.
空间复杂度
递归算法每次要储存返回的信息,需要附加额外的堆栈空间。快速排序法空间复杂度约为S(lgn).
稳定性
由于在快速排序中相同元素的相对位置会发生改变,所以快速排序法是不稳定的。