目录
快排的主要思想是基于分治思想的
快排的步骤
假设一列数,左边界的数为q[l],右边界的数为q[r]
1.确定分界点x:可以是左边界,右边界,中间值或者随机
2.调整区间:以x为分界点,使第一区间(x左边)的数都是小于等于x的数,第二区间(x右边)的数都是大于等于x的数(注意,两个区间长度不一定相等)
3.递归处理:先给左区间排序,再给右区间排序,则整个区间就排序完成了
4.实现方法:
①左指针i,右指针j,*i<x(使用*表示指向的对象的值),则i右移,*i>=x,则i停止移动,去移动j
②*j>x则j左移,*j<=x则停止,此时,*i,*j都是不符合位置的数,所以二者交换(swap),交换完成后ij再各往中间移动一位
③重复上述操作,直到i和j停止时二者相遇或者i右j左,这时i右是>=x的,j左是<=x的
代码详解
const int N = 1e6 + 10;//设置数组最大值
int n;
int q[N];
//快速排序函数 函数参数:排序数组,数组左边界,数组右边界
void quick_sort(int q[], int l, int r)
{
//判边界
if (l >= r) return;
//确立分界点
int x = q[l]/*可以换,比如取右边界等*/, i = l - 1, j = r + 1;
//为什么i,j不分别取左右边界?因为再尽行后续位置的排序时,要先移动,再判断是否符合条件,唯独第一次在边界位置不需要移动后判断
//所以为了整体更“美观”,改为这种写法,使得在比较左右边界是否符合情况之前也需要先进行移动
while (i < j)
{
//移动
do { i++; } while (q[i] < x);
do { j--; } while (q[j] > x);
//执行到此则i,j均已停止,二者进行交换
if (i < j) swap(q[i], q[j]);
}
//递归处理左右两边
quick_sort(q, l, j);
quick_sort(q, j + 1, r);//切记要么i-1/i,要么j/j+1,但是如果用i/j,上面x就不能取左/右边界,同样不要一个i一个j,会陷入死递归
//比如输入的数组是54321,在递归的时候由于i和j都是0,所以会导致上面函数直接返回,下面的函数传入的左边界一直是0,陷入死递归,可以调试查看
}
为什么i,j不分别取左右边界?因为再尽行后续位置的排序时,要先移动,再判断是否符合条件,唯独第一次在边界位置不需要移动后判断
所以为了整体更“美观”,改为这种写法,使得在比较左右边界是否符合情况之前也需要先进行移动