由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("%.2f\n", 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 1001
typedef 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 %f\n",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 20
18 15 10
75 72 45
输出
18.000000 15.000000 10.000000
15.000000 10.000000
18.000000 15.000000
18.000000 10.000000
15.000000 10.000000 18.000000
N=4:
输入
4 20
18 15 10 12
75 72 45 57.6
输出
18.000000 15.000000 10.000000 12.000000
18.000000 15.000000
10.000000 12.000000
15.000000 12.000000
18.000000 12.000000
18.000000 10.000000
15.000000 12.000000 10.000000 18.000000
N=5;
输入
5 20
18 15 10 12 10
75 72 45 57.6 160
输出
18.000000 15.000000 10.000000 12.000000 16.000000
18.000000 15.000000
12.000000 16.000000
10.000000 16.000000
10.000000 12.000000
15.000000 16.000000
15.000000 12.000000
18.000000 12.000000
18.000000 10.000000
16.000000 15.000000 12.000000 10.000000 18.000000
其中结构体数组的结构体成员stock不要出现相同的情况,不然不好观察。由以上实验可以看出,当qsort的回调函数返回0时,如果假设所比较的两个元素留在原位保持不变,就能得到如上图所示的结果,因此,可以得出结论,当回调函数返回值为0时,qsort会让当前所比较的这两个元素暂时保持不动。