我们知道快排的一般步骤是:
1.选取最左边的数为基准数;
2.从右边开始选取一个小于基准数的元素;
3.从左边开始选取一个大于基准数的元素;
4.交换这两个元素;
5.重复2、3、4步直至左右两边移到同一位置,交换基准数与当前元素
void quick_sort(int *begin, int *end)
{
int *left = begin, *right = end;
if(begin >= end)
return ;
int pos_x = *begin;
while(begin < end)
{
while(begin < end && *end >= pos_x)
end --;
while(begin < end && *begin <= pos_x)
begin ++;
if(begin < end)
swap(*begin, *end);
}
*left = *begin;
*begin = pos_x;
quick_sort(left, begin - 1);
quick_sort(begin + 1, right);
}
我们发现上面的代码进行了多次swap,所以我们可以进行优化,如下:
void quick_sort(int *begin, int *end)
{
int *left = begin, *right = end;
if(begin >= end)
return ;
int pos_x = *begin;//记录基准值,同时给第一个位置空出来
while(begin < end)
{
while(begin < end && *end >= pos_x)
end --;
if(begin < end)
*begin ++ = *end;//将之前空出来的位置放入小于基准值的数
while(begin < end && *begin <= pos_x)
begin ++;
if(begin < end)
*end -- = *begin;//将之前空出来的位置放入大于基准值的数
}
*begin = pos_x;//最后将基准值归位
quick_sort(left, begin - 1);
quick_sort(begin + 1, right);
}
由于快排在某些情况下的时间复杂度会退化成O(
)
比如在有序的情况下,我们以最左值作为基准的话,就会使算法退化成O(
)
这时我们可以选择采用随机选择基准值或者选择中间元素为基准值的方法去解决。
同时,我们可以选择双路遍历序列的方式来使快排更加稳定
void quick_sort(int *begin, int *end)
{
int *left = begin, *right = end;
if(begin > end)
return ;
int pos_x = *(begin + (int)(end - begin) / 2);
while(begin <= end)
{
while(*begin < pos_x)
begin ++;
while(*end > pos_x)
end --;
if(begin <= end)
{
swap(*begin, *end);
begin ++;
end --;
}
}
if(left < end)
quick_sort(left, end);
if(begin < right)
quick_sort(begin, right);
}