采用分治的方法
1.确定分界点
指定x为分界值,x可为数组最左端值 最右端值 数组中间值 任意值。
2.调整区间
将数组分成x左边的值都<=x,右边的值都>=x。
(1)暴力方法
开两个数组 a,b。遍历q,<=x的值放a,>x的值放b。再把a,b放到q中。为什么暴力呢 ?因为需要用到两个额外的空间。但是时间复杂度还是线性的。
(2)更好方法
为数组加两个指针i,j。i初始在最左端,j初始在最右端。接下来移动两个指针。如果i指向的值满足<x,i右移;反之,停下来,并开始移动j,如果j指向的值满足>x,j左移;反之,判断i?j,如果i<j,交换i,j指向的值,继续开始重复上述i,j的移动;如果i>=j,即i,j已经相遇了,那么说明区间已经分好了。
3.递归处理左右两段。
备注:学习自用
代码:
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
}
续:做一道题时出现了tle,超时了。原因是有一组测试数据的第一个值是数组中的最大值,这种是最坏的情况,时间复杂度为O(n^2)。解决办法是把分组基准换为了数组中间值。其实也可以搞一个随机选择,一把情况下不会超时。(了解到更深层次的原因,复杂度的推算看不懂)
用 sort()排序没问题,了解到sort的原理是多种排序方式的复杂有规则的结合。且时间复杂度为nlog n。
续:终止条件肯定是i先检测到值不满足<x,让后j也检测到值不满足>x,此时i>j,i与j已经交叉了。接着进行深一层的递归处理。