排序方法实验——快速排序(递归)
原理
每次递归中,函数的主要目的就是将所有小于待排序数字的数放到数字左侧,右侧同理。
然后将数组从待排序数位置一分为二(不包含当前调用中已经排序好的数字)分别排序
-
二分法
在调用中,我们将传入数组的第一位当作待排序数字,然后将所有数字按大小放到待测数字两侧(这里实际上实现时是将待排序数字插到排列中去实现);然后左右分别缩小问题
-
递归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编写,编译出错请各自对照自己的编译规则修改
- 本文案仅供班级内小组任务参考使用,如有冒犯他人著作权请及时私信删除。
相关基础知识不做赘述 ↩︎