1 条题解

  • 0
    @ 2026-8-18 11:53:04

    填空答案

    位置 填入内容 作用
    if(p.age>=60&&q.age<60) return ...; 1 p 是老人、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;
    }
    

    思路讲解

    整体结构

    程序分三步:

    1. 读入:每个病人存成一个结构体(姓名、年龄、登记序号),id = i 记录他是第几个登记的;
    2. 排序:sortup 用冒泡排序,相邻两人比较,如果"后面的应该排前面"(comp(a[i+1], a[i]) 返回 1)就交换;
    3. 输出:按排好的顺序逐行输出姓名。

    逐个填空解释

    空 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 是逐层筛选的关系,顺序换掉就会出错:

    1. 先分出"一老一少"(前两行);
    2. 剩下的要么都老要么都少,先处理"都少"(按登记序);
    3. 最后剩下的必然是"都老",同龄按登记序,不同龄按年龄降序。

    如果把"都少"的判断删掉,两个非老人会掉进后面 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
    上传者