算法描述: 快速排序是一种分治的排序算法。 1、取出一个分割点,使数组左边的元素不大于该分割点的值,数组右边的元素不小于该分割点的值; 2、将数组的左半部分排序; 3、将数组的右半部分排序;
算法实现: class Quick
{
public:
static bool sort(int *a, int lo, int hi)
{
if(hi <= lo) return true;
int p = partition(a, lo, hi);
sort(a, lo, p – 1);
sort(a, p + 1, hi);
return true;
}
static int partition(int *a, int lo, int hi)
{
int i = lo, j = hi + 1;
int v = a[lo];
while(true)
{
/* 扫描左右,检查扫描是否结束并交换元素 */
while(a[++i] < v)
{
if(i == hi) break;
}
while(v < a[–j])
{
if(j == lo) break;
}
if(i >= j) break;
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
/* 将v = a[j]放入正确的位置 */
a[lo] = a[j];
a[j] = v;
return j;
} }; 上述实现中,我们选取了a[lo]作为切分元素。在切分的过程中,我们保证左指针i左侧的元素不大于切分元素,右指针j右侧的元素不小于切分元素。当两个指针相遇时,我们只需要将切分元素a[lo]和a[j]进行交换,然后返回j即可。
时间复杂度: 快速排序最好的情况是每次都正好能将数组对半分,在这种情况下快速排序所用的次数正好满足分治递归的f(n) = 2 * f(n/2) + n,“2 * f(n/2) ”表示将两个子数组排序的成本,n表示切分元素和当前数组比较的成本。 公式推导: f(n) = 2 * f(n/2) + n = 4 * f(n/4) + 2 * n = 8 * f(n/8) + 3 * n … = n + n * lg(n)
空间复杂度: 快速排序是原地排序,由于使用递归所以需要一个比较小的辅助栈(lg(n))。
稳定性: 快速排序是不稳定的,因为快速排序中不仅仅是相邻元素的交换。
适用情景: 快速排序可能是应用最广泛的算法,实现简单,速度快,不依赖输入情况,只用到一个很小的辅助栈(lg(n))。