快速排序的方法:
假设现在对 6 1 2 7 9 3 4 5 10 8这10个数进行排序。
分析:
1、我们首先要找一个数作为基准数(当然,基准数是自己随便定的,一般是找第一个数作为基准数)
2、分别从初始序列”6 1 2 7 9 3 4 5 10 8“两端开始”探测“。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换它们。这里可以用两个变量i和j,分别指向序列最左边和最右边。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即j=10),指向数字8。

3、首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,下面会解释为什么要从最右边开始。
4、哨兵j一步一步的向左挪动,直到找到一个小于6的数停下来。

5、哨兵i再一步一步向右挪动,直到找到一个大于6的数停下来。

6、最后哨兵j停在了数字5面前,哨兵i停在了数字7面前,然后把它们交换一下


到此,第一次交换结束。接下来还是哨兵j先继续移动,和上面的方法一样,经过多次交换后,哨兵i和哨兵j相遇了(见证爱情的时刻,我都有点心动了,哈哈哈,为了让他们俩再一个方块上面,他们每人减了50公斤。。)

然后让基准数6和3进行交换

这样就完成了一趟”快排“,此时6也就归位了。下面就是根据上面的方法,排序6前面的3 1 2 5 4 和后面的 9 7 10 8就ok了。
可能上面的你没有看懂,下面来一个霸气的图来描述一下整个算法的处理过程:
(由于过程太长,就没有豆包夫妇了。。见谅见谅,哈哈哈)

代码如下:
#include<stdio.h>
void quickSort(int a[],int left,int right)
{
if(left>right)//如果左边大于右边就结束
return ;
int temp = a[left];//temp中存的就是基准数
int i=left;//创建哨兵i
int j=right;//创建哨兵j
while(i<j)
{
while(a[j]>=temp&&i<j)//要先从后面往前找
{
j--;
}
while(a[i]<=temp&&i<j)//从前面往后找
{
i++;
}
if(i<j)//没有相遇时,就已经找到了
{
int t = a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left] = a[i];//相遇时
a[i]=temp;
for(int i=0;i<10;i++)//输出每一趟的快排
{
printf("%d ",a[i]);
}
printf("\n");
quickSort(a,left,i-1);//继续处理左边的
quickSort(a,i+1,right);//继续处理右边的
}
int main()
{
// int n;
int a[10]={6,1,2,7,9,3,4,5,10,8};
//scanf("%d",&n);
//for(int i=0;i<n;i++)
// {
// scanf("%d",&a[i]);
// }
quickSort(a,0,10-1);
return 0;
}
运行结果:
3 1 2 5 4 6 9 7 10 8
2 1 3 5 4 6 9 7 10 8
1 2 3 5 4 6 9 7 10 8
1 2 3 5 4 6 9 7 10 8
1 2 3 4 5 6 9 7 10 8
1 2 3 4 5 6 9 7 10 8
1 2 3 4 5 6 8 7 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
看到这里,你可能会觉着代码a[j]>=temp&&i<j中的i<j是多余的,但其实时错误的,因为如果你去掉的话,当哨兵j遇到小于temp的值时会停止,但是哨兵i和哨兵j相遇的时候i==j的时候哨兵i并不会停止前进,因为哨兵i遇到的值是哨兵j遇到后停止的那个值,所以哨兵i会继续往前走,因此不能省。(读到这里,你如果不能理解,你就在笔记本上写一趟快排的步骤,你就会明白了)
下面解决一下,为什么要从后面开始?
如果选取最左边的数a[left]作为基准数,那么先从右边开始可保证i,j在相遇时,相遇数是小于基准数的,交换之后temp所在位置的左边都小于temp。但先从左边开始,相遇数是大于基准数的,无法满足temp左边的数都小于它。所以进行扫描,要从基准数的对面开始。(同样,你可以用笔,写一列数试一试就能够理解了)
本文详细解析了快速排序算法的实现过程,通过实例演示了如何选择基准数,并使用双指针技术进行元素交换,最终达到排序的目的。同时,文章还提供了完整的C语言代码实现,帮助读者深入理解快速排序的运作机制。
6772

被折叠的 条评论
为什么被折叠?



