排序方法学习——快速排序

排序方法实验——快速排序(递归)

原理

每次递归中,函数的主要目的就是将所有小于待排序数字的数放到数字左侧,右侧同理。
然后将数组从待排序数位置一分为二(不包含当前调用中已经排序好的数字)分别排序

  • 二分法

    在调用中,我们将传入数组的第一位当作待排序数字,然后将所有数字按大小放到待测数字两侧(这里实际上实现时是将待排序数字插到排列中去实现);然后左右分别缩小问题

  • 递归1
    我们利用递归的特点将任务先从大到小一层层排列开来,然后从最内层的调用完成计算(即执行return语句)后将结果传回上一层,以此类推完成任务。

流程介绍

随手画的,看懂就行

解释原理

  • 每次调用都只是初步排序
    现在有一组数据:5 3 6 4 1 2 9
    进入调用中,可见待排序数(tem)即为5;快针(fast)指向最后一个数9;慢针(slow)指向待排序数后一个数3。
    进入循环(fast > slow),由快针(fast)先走,来到数字2时停止(in[tem] > in[fast]),快针循环结束。
    来到慢针,慢针来到数字6时停下(in[tem] < in[slow]),此时可见快针所指数字小于慢针所指数字(in[fast] < in[slow])。我们的目的是将数字按大小排在待排序数两端,所以我们交换这两个值。现在的数据为5 3 2 4 1 6 9
    交换完成,外层循环继续。此时快针停在数字1,慢针开始循环后与快针在数字1位置处重合,外层循环结束。
    交换待测数与快针位置,得到1 3 2 4 5 6 9。从数字5处将数组分成1 3 2 4和6 9两部分,分别放入下一次函数中。
    最后分离时每个组中仅剩一个数字(head > end不成立),结束当前函数。
    至此,调用的最内层才结束,接连结束上一层调用,直至最外层结束,递归结束。

实现

#include <stdio.h>

void change(int* x,int* y);//声明交换函数
void sort(int* in,int head,int end);//声明排序函数

void main(){
    int lim;
    scanf("%d",&lim);
    int in[lim];
    for (int i = 0;i < lim;i++) scanf("%d",in+i);
    printf("原始数据为:");
    for (int i = 0;i < lim;i++) printf("%d ",in[i]);
    printf("\n");//获取并确认原始数据

    sort(in,0,lim - 1);//调用,注意数组的长度防止越界

    printf("排序后:");//输出结果
    for (int i = 0;i < lim;i++) printf("%d ",in[i]);
}

void change(int* x,int* y){
    int tem = *x;//缓存x地址内容
    *x = *y;//将y地址内容赋值给x地址
    *y = tem;//将缓存内容赋值给y地址
}

void sort(int* in,int head,int end){
    if (head >= end) return;//退出递归条件:头位置与尾位置相同,即进入下一次调用的仅一位

    /*单次调用中使用的变量*/
    int tem = head;//数组的第一个元素为待排序数字
    int slow = head + 1;//慢针由数组第二位(待排序位下一位)向右走
    int fast = end;//快针由数组末尾向左走

    while(fast > slow){
        /*其中有一点要注意:一定是快针先走(右往左),详情见文章*/
        while (fast > slow && in[fast] >= in[tem]) fast--;//快针往左走,找到比待排序元素小的元素
        while (fast > slow && in[slow] <= in[tem]) slow++;//慢针往右走,找到比待排序元素大的元素
        if (fast > slow) change(&in[fast],&in[slow]);//交换快慢针元素
    }
    /*循环结束时,快慢针相遇,而且由第三步可想所有比待测元素小的都在目前待测针的左侧,右侧同理*/

    if (in[fast] < in[tem]){
        change(&in[tem],&in[fast]);
        tem = fast;
    }//防止快慢针交换值时出现过交换,检验待排序元素右侧第一个元素的大小

    sort(in,head,tem - 1);//左侧递归
    sort(in,tem + 1,end);//右侧递归
    //此时的二分递归不包含当前次调用中已经排序好的元素
}

运行效果

本人电脑运行结果

参考文案与支持

  • 程序实现参考
  • 使用vsCode2022编写,编译出错请各自对照自己的编译规则修改
  • 本文案仅供班级内小组任务参考使用,如有冒犯他人著作权请及时私信删除。

  1. 相关基础知识不做赘述 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值