快速排序又叫做分区交换排序,这是一种平均性能非常好的排序方法,属于交换排序的一种。
其基本思想是:任取排序表中的某个数据元素(例如取第一个数据元素)作为基准,按照该数据元素的关键字大小,将整个排序表划分为左右两个子表:左侧子表中所有数据元素的关键字都小于或等于基准数据元素的关键字,右侧子表中所有数据元素的关键字都大于基准数据元素的关键字,基准数据元素则排在这两个子表中间(这也是该数据元素最终应安放的位置),然后分别对这两个子表重复施行上述方法的快速排序,直到所有的子表长度为1,则排序结束。很显然,快速排序过程是一个递归的过程。
程序如下:
public class App
{
public static void main(String[] arg) {
int[] array= {23,31,49,31,6,19};
quickSort(array, 0, array.length-1);
System.out.println(Arrays.toString(array));
}
static void quickSort(int[] array,int low,int high) {
int i=low,j=high;
int base=array[low];
if(i<j) {
while(i<j) {
while(i<j && base<array[j])
j--;
if(i<j) {
array[i]=array[j];
i++;
}
while(i<j && base>=array[i])
i++;
if(i<j) {
array[j]=array[i];
j--;
}
}
array[i]=base;
quickSort(array, low, i-1);
quickSort(array, i+1, high);
}
}
}
运行结果:
[6, 19, 23, 31, 31, 49]
如果每次划分对一个数据元素定位后,左右两侧的子表长度相同,然后对再对两个长度减半的子表进行排序,这是最理想的情况。此时的时间复杂度为O(nlog2n)。
这只是最理想的情况,所以应该用平均时间复杂度评价该算法。该算法的平均复杂度为O(nlog2n),空间复杂度为O(log2n)。
如果排序表已经按照从小到大排好序,每次划分只会得到比上一次少一个数据元素的子表(另一个元素为空),这样,必须经过n-1趟才能把所有数据元素排好序。此时排序数据已经退化到了冒泡排序的水平。时间复杂度为O(n^2),空间复杂度为O(n)。
合理选择基准数据元素很重要,因此一种改进的方法是,每次选取排序表中的第一个数据元素,最后一个、中间一个,然后取三者大小居中的数据元素作为基准。
快速排序是一种不稳定的排序方法。对于关键字相同的数据元素,排序后可能会颠倒次序。严格地说,只是对于较大n,就平均情况而言,快速排序是“快速”的。