快速排序,就像他的名字,相对而言十分快速,时间复杂度较低,所以在对程序运行时间有一定要求的场合可以选择快速排序来进行数据的排序
快速排序首先在步骤上分为:
- 首先选取一个基准数,直接取首元素即可
- 对于从左往右降序排序,将比基准数小的数放到基准数左边,比基准数大的放到右边,如果一个在右边的数比基准数大,那就放着不动,继续向左比较,直到找到一个比基准数小的数,然后放到基准数左边,然后开始比较左边,左边也是同理,如果一个数在基准数左边但比基准数小的话,那就不动继续向右移动,直到找到一个比基准数大的数,然后放到基准数右边,然后再回到右边去比较,依次循环直到左右重合,循环停止,将原来的数组分成两组
- 将基准数放到左右重合也就是中间的位置上,然后递归调用,此时因为将一个数组已经拆成了两部分,所以需要两个函数进行递归,递归一直到左右重合时就停止,这步很重要不小心就会造成无限递归的死循环
要注意的是,如果基准数选的是首元素,也就是左边第一个元素,那应该先从右往左比较,否则可能会出现数据覆盖的问题
首先给一个数列,并且将首元素选为基准数,将基准数赋给一个变量
然后用末尾的78来跟90比较,如果比90小,那就将78放到90的位置上去
然后在回到左边进行比较,由于从12一直到99之前没有一个比基准数大的数,故一直循环到99停止,此时99又比90大故,要将99放到右边,由于左边一直没有比基准数大的数,所以右边我们还一次都没有循环,所以此时将99在放到78的位置
现在这个数列就已经被我们遍历完了,最后记得把基准数放回到刚刚我们左右重合的中间位置
然后分成了两个数列
然后再分别递归排序这两部分数列
由于右边数列只有一个数,故无法再进行排序,我们只需要将注意力放在左边数列上
新的一次递归数列排序开始的位置应该是0而结束的位置是刚刚重合的中间位置也就是90的位置-1,所以我们需要进行排序的数列变成了
此时首元素78会被再当成基准数来继续进行比较,由于33小于78,故将33放到78的位置上
然后再回到左边一直循环比较,如果没有遇到比78大的数就一直循环比较直到找到一个比78大的数,最后再将78放到左右重合的位置,将数列再一分为二,再进行新的一次递归
代码
#include<stdio.h>
int fast(int* y,int begin,int end)
{
int temp=y[begin];
//将结尾位置保存一下,因为之后的运算会改变end值,end会逐渐向前移动
//,而最后递归的时候end还得是数组的尾元素,不能发生变化
int endTemp=end;
//设定递归条件,左右不可相等(重合)如果相等那就return
if(end>begin)
{
//循环条件,左右不可相等(重合),如果相等,那就一次排序分组完毕,开始将分好的两组数组再递归进行排序
while(begin<end)
{
//向左移动
while((begin<end)&&(temp<=y[end]))
end--;
y[begin]=y[end];
//向右移动
while((begin<end)&&(temp>y[begin]))
begin++;
y[end]=y[begin];
}
//基准元素放到中间左右重合的位置上
y[begin]=temp;
//分组递归,前一组数组为首元素到
fast(y,0,begin-1);
fast(y,begin+1,endTemp);
}
return 0;
}
int main()
{
int y[]={22,12,1,33,17,5,10,89,88,30,21,11,11};
fast(y,0,(sizeof(y)/sizeof(int))-1);
for(int i=0;i<sizeof(y)/sizeof(int);i++)
printf("%d ",y[i]);
return 0;
}