易于实现、原地排序、复杂度低,把这些优点聚于一身,很容易使人想到快排——一种上课、考试、找工作总能遇到的算法。
算法思想:
分治的理念,将问题转化为把数组切成两段,再对两段分别排序的问题。其中需要注意的是切分方法:
1、在原数组中取一个元素p,逐次与其他元素比较,把小于p的所有元素放在p的左边,大于p的放右边——这样,原数组就以p为界线,被切成两段
2、p的位置已经是其最终排序后的位置了,只需再对左右两段重复1中的过程便可使所有元素找到最终的位置
代码示例:
#define SWAP(A, B) do{(A) ^= (B); (B) ^= (A); (A) ^= (B);} while(0)
int partition(int array[], int left, int right) {
int i = left - 1;
int divide = array[right];
int j;
for(j = left; j < right; j++) {
if(array[j] < divide) {
i++;
SWAP(array[i], array[j]);
}
}
SWAP(array[i+1], array[j]);
return i + 1;
}
void _quick_sort(int array[], int left, int right) {
if(left < right) {
int p = partition(array, left, right);
_quick_sort(array, left, p - 1);
_quick_sort(array, p + 1, right);
}
}
void quick_sort(int array[], int len) {
_quick_sort(array, 0, len - 1);
}
虽说快排思路简单,但实际使用时仍有诸多问题值得注意,以上代码只是一种简易实现,多处有待优化,此点读者可自行思索验证,后续我会补充。
复杂度分析:
假设每次切分都能从中间一分为二,则分治方程可表示为T(n) = 2*T(n/2) + n,故时间复杂度O(nlogn),在最坏情况下达到O(n^2);如果采用递归实现,则递归堆栈空间复杂度为O(n);
重要特性:
1、原地排序
2、不稳定排序
3、算法效率取决于切分数组是否均匀,切分函数应适应具体数据分布