1 条题解
-
0
填空答案
位置 填入内容 作用 if(p.age>=60&&q.age<60) return ...;1p 是老人、q 不是 → p 排前面 if(p.age<60&&q.age<60) return ...;p.id<q.id都不是老人 → 按登记先后 return ...; // 老年人年龄大的优先p.age>q.age都是老人 → 年龄大的在前 {{FILL}} // 初始化标志位flag=0;冒泡排序每轮开始前清零 完整代码(原模板 + 填空)
#include<stdio.h> typedef struct { char name[20]; int age; int id; // 登记顺序 }na; // 比较函数:返回1表示p应该在q前面 int comp(na p,na q) { if(p.age>=60&&q.age<60) return 1; // 老年人优先 if(p.age<60&&q.age>=60) return 0; // 老年人优先(题目要求这里返回0) if(p.age<60&&q.age<60) return p.id<q.id; // 也可以p.id<q.id if(p.age==q.age) return p.id<q.id; // 年龄相同按登记顺序 return p.age>q.age; // 老年人年龄大的优先 } void sortup(na a[],int n) { na r; int flag=1; while(flag) { flag=0; // 初始化标志位 for(int i=0; i<n-1; i++) { // 如果a[i+1]应该在a[i]前面,则交换 if(comp(a[i+1], a[i])) { r=a[i]; a[i]=a[i+1]; a[i+1]=r; flag=1; // 发生了交换,需要继续排序 } } } } int main() { int n; scanf("%d",&n); na patient[100]; for(int i=0; i<n; i++) { scanf("%s %d", patient[i].name, &patient[i].age); patient[i].id = i; // 记录登记顺序 } sortup(patient, n); for(int i=0; i<n; i++) { printf("%s\n", patient[i].name); } return 0; }思路讲解
整体结构
程序分三步:
- 读入:每个病人存成一个结构体(姓名、年龄、登记序号),
id = i记录他是第几个登记的; - 排序:
sortup用冒泡排序,相邻两人比较,如果"后面的应该排前面"(comp(a[i+1], a[i])返回 1)就交换; - 输出:按排好的顺序逐行输出姓名。
逐个填空解释
空 1:
return 1;→ 填1走到这一行时,p 是老人(≥60)、q 不是。按"老年人优先",p 应该排前面,而
comp的约定是"返回 1 表示 p 在前",所以返回 1。空 2:
p.id<q.id走到这一行说明前两个条件都不成立:要么两人都是老人,要么两人都不是。但注意这行专门判断"两人都不是老人"的情况——非老人唯一的排序依据是登记先后,登记早(id 小)的在前。
p.id < q.id是 C 里的关系表达式,成立时值就是 1,不成立就是 0,正好符合 comp 的返回约定。空 3:
p.age>q.age能走到这里,说明两人都是老人且年龄不相同(年龄相同的在前一行已处理)。老年人年龄从大到小看病,所以 p 年龄更大(
p.age > q.age)时 p 排前面,返回 1。空 4:
flag=0;这是冒泡排序的"提前退出"机制:每轮扫描开始时假设数组已经排好(flag 置 0),一轮下来如果一次交换都没发生,
while(flag)的条件就是假,排序结束。如果漏掉这行,flag永远是 1,程序会死循环。comp 四个判断的顺序为什么不能乱
这四个 if 是逐层筛选的关系,顺序换掉就会出错:
- 先分出"一老一少"(前两行);
- 剩下的要么都老要么都少,先处理"都少"(按登记序);
- 最后剩下的必然是"都老",同龄按登记序,不同龄按年龄降序。
如果把"都少"的判断删掉,两个非老人会掉进后面
p.age > q.age的比较里,变成"年轻的非老人排前面",直接违反规则。样例演算
输入:
5 021075 40 004003 15 010158 67 021033 75 102012 30读入后(id 从 0 开始):
姓名 年龄 id 类别 021075 40 0 非老人 004003 15 1 010158 67 2 老人 021033 75 3 102012 30 4 非老人 排序结果:老人先按年龄降序——021033(75)、010158(67);非老人按登记序——021075(id 0)、004003(id 1)、102012(id 4)。
输出:
021033 010158 021075 004003 102012易错点
- 60 岁算老人(
>= 60),59 岁不算,临界数据最容易判错。 - 空 2、空 3 填的是表达式(
p.id<q.id、p.age>q.age),不是 0 或 1——C 的比较结果本身就是 0/1。 - 空 4 漏写或写错位置会导致死循环;写在 for 循环里面则起不到"整轮无交换才退出"的作用。
comp(a[i+1], a[i])的实参顺序是"后面那个人在前"——判断的是相邻两人是否逆序,别把参数顺序颠倒。- 结构体整体赋值
r = a[i]会连 name、age、id 一起复制,这是 C 结构体的默认行为,不用逐个成员交换。
- 读入:每个病人存成一个结构体(姓名、年龄、登记序号),
- 1
信息
- ID
- 20
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者
吉公网安备22010402001496号