首页 > 编程知识 正文

qsort函数实现

时间:2023-05-05 17:57:06 阅读:263109 作者:711

由PAT乙级1020题所引发:
https://pintia.cn/problem-sets/994805260223102976/problems/994805301562163200

这是某个人的解题代码:

#include <stdio.h>#include <stdlib.h>#define MAXN 1001/*定义月饼结构体为mooncake*/typedef struct {float stock; //库存。float price; //每款月饼总价。float each; //每款月饼单价。} mooncake;int cmp ( const void *a, const void*b ) {mooncake c1 = *(mooncake *)a; //将指针a强制转化为mooncake结构体类型。mooncake c2 = *(mooncake *)b;return c2.each > c1.each; //按单价each降序返回。}int main(void) {int N, i;float D, total;mooncake cake[MAXN];scanf("%d %f", &N, &D);for ( i = 0; i < N; i++ )scanf("%f", &cake[i].stock);for ( i = 0; i < N; i++ )scanf("%f", &cake[i].price);for ( i = 0; i < N; i++ )cake[i].each = cake[i].price / cake[i].stock; /*数组名,数组大小,每个数组元素大小,比较函数*/qsort ( cake, N, sizeof(mooncake), cmp ); //sizeof(cake[0])也行。total = 0; /*月饼已经按单价降序排号,只需遍历*/for( i = 0; i < N && D > 0; i++ ) {if ( cake[i].stock <= D ) { //某款月饼库存比需求量低。total += cake[i].price; //这款月饼总价全部放入销售额。D -= cake[i].stock; //需求量扣除这款月饼的库存。} else { //某款月饼的库存满足了需求量。total += D * cake[i].each; //销售额 = 需求量 * 这款月饼单价。D = 0; //需求置零,退出循环。}}printf("%.2fn", total);return 0;}

参考文献:https://blog.csdn.net/YelloJesse/article/details/82431875?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

他在其中使用了qsort函数,返回值取决于c1和c2所指向结构体的成员变量each的大小关系,我看到他在回调函数最后所写的是:

return c2.each > c1.each;

我就在想,假如出现了c2.each<c1.each的情况,那么return的值就是0了,要知道C语言的关系表达式的结果只有0和1,在百度上的说法是:

如果compar返回值等于0(= 0),那么p1所指向元素与p2所指向元素的顺序不确定;

那么当出现了c2.each<c1.each的情况时,qsort函数是如何保证序列中的元素还能降序排列的?
我在这里记下自己的这个问题,下面是网上找的qsort函数源码:
https://www.cnblogs.com/zpchya/p/10745643.html

事后觉得,看源码是个愚蠢的决定,因为后来我发现上面这个博客园的链接和《C标准库》第354页所提供的qsort源码竟然是两个版本,也是怪了。

其实在这种情况下,把qsort当成黑箱子,弄个测试程序,可能还更好,测试程序如下:

#include<stdio.h>#include<stdlib.h>#define MAXN 1001typedef struct{ float stock; float price; float each;}mooncake;int cmp(const void* a,const void* b){ mooncake c1=*(mooncake*)a; mooncake c2=*(mooncake*)b; printf("%f %fn",c1.stock,c2.stock); return c2.each>c1.each;}int main(){ int N; float D,total; mooncake cake[MAXN]; scanf("%d %f",&N,&D); for(int i=0;i<N;i++)scanf("%f",&cake[i].stock); for(int i=0;i<N;i++)scanf("%f",&cake[i].price); for(int i=0;i<N;i++)cake[i].each=cake[i].price/cake[i].stock; for(int i=0;i<N;i++)printf("%f ",cake[i].stock); printf("n"); qsort(cake,N,sizeof(mooncake),cmp); for(int i=0;i<N;i++)printf("%f ",cake[i].stock); printf("n"); total=0; return 0;}

测试N为3、4、5的情况下程序的输出结果,同时在回调函数里面加入printf函数,判断当前比较的是哪两个元素,在主函数调用qsort的前后各放置for循环,观察变化。
实验结果如下:
N=3:
输入

3 2018 15 1075 72 45

输出

18.000000 15.000000 10.000000 15.000000 10.00000018.000000 15.00000018.000000 10.00000015.000000 10.000000 18.000000

N=4:
输入

4 2018 15 10 1275 72 45 57.6

输出

18.000000 15.000000 10.000000 12.000000 18.000000 15.00000010.000000 12.00000015.000000 12.00000018.000000 12.00000018.000000 10.00000015.000000 12.000000 10.000000 18.000000

N=5;
输入

5 2018 15 10 12 1075 72 45 57.6 160

输出

18.000000 15.000000 10.000000 12.000000 16.000000 18.000000 15.00000012.000000 16.00000010.000000 16.00000010.000000 12.00000015.000000 16.00000015.000000 12.00000018.000000 12.00000018.000000 10.00000016.000000 15.000000 12.000000 10.000000 18.000000

其中结构体数组的结构体成员stock不要出现相同的情况,不然不好观察。由以上实验可以看出,当qsort的回调函数返回0时,如果假设所比较的两个元素留在原位保持不变,就能得到如上图所示的结果,因此,可以得出结论,当回调函数返回值为0时,qsort会让当前所比较的这两个元素暂时保持不动。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。