最常用的排序——快速排序(豆包”鹊桥“相见)

本文详细解析了快速排序算法的实现过程,通过实例演示了如何选择基准数,并使用双指针技术进行元素交换,最终达到排序的目的。同时,文章还提供了完整的C语言代码实现,帮助读者深入理解快速排序的运作机制。

快速排序的方法:
假设现在对 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左边的数都小于它。所以进行扫描,要从基准数的对面开始。(同样,你可以用笔,写一列数试一试就能够理解了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值