PTA_数据结构与算法_7-47 打印选课学生名单 (25分)

假设全校有最多40000名学生和最多2500门课程。现给出每个学生的选课清单,要求输出每门课的选课学生名单。

输入格式:
输入的第一行是两个正整数:N(≤40000),为全校学生总数;K(≤2500),为总课程数。此后N行,每行包括一个学生姓名(3个大写英文字母+1位数字)、一个正整数C(≤20)代表该生所选的课程门数、随后是C个课程编号。简单起见,课程从1到K编号。

输出格式:
顺序输出课程1到K的选课学生名单。格式为:对每一门课,首先在一行中输出课程编号和选课学生总数(之间用空格分隔),之后在第二行按字典序输出学生名单,每个学生名字占一行。

输入样例:

10 5
ZOE1 2 4 5
ANN0 3 5 2 1
BOB5 5 3 4 2 1 5
JOE4 1 2
JAY9 4 1 2 5 4
FRA8 3 4 2 5
DON2 2 4 5
AMY7 1 5
KAT3 3 5 4 2
LOR6 4 2 4 1 5

输出样例:

1 4
ANN0
BOB5
JAY9
LOR6
2 7
ANN0
BOB5
FRA8
JAY9
JOE4
KAT3
LOR6
3 1
BOB5
4 7
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
5 9
AMY7
ANN0
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MaxName 5
#define MaxC 20
typedef struct ListNode *List;
struct ListNode{
    char Name[MaxName];//学生姓名
    List Next;//指针域
};//链表节点
struct StudentNode{
    char Name[MaxName];//学生姓名
    int nC;//该生选课门数
    int C[MaxC];//该学生选择的课程编号
} *Student;//输入的学生信息
struct CourseNode{
    int Counter;//该课程的选课人数
    List Ptr;//链表头指针
} *Course;//课程链表的表头

int CmpName(const void *a, const void *b){//调用qsort对学生姓名按字典序排序时用到的比较函数
    return strcmp(((const struct StudentNode*)a)->Name, ((const struct StudentNode*)b)->Name);
}
void Read_and_Sort(int *N, int *K);//读入并存储输入数据,再按学生姓名排序
List NewNode(char *name);//建立链表节点
void InsertCourse(int N, int K);//按姓名倒序,将学生的选课记录插入相应链表
void Output(int K);//对K门课,输出选课学生名单

int main()
{
    int N, K;
    Read_and_Sort(&N, &K);//读入并存储输入数据,再按学生姓名排序
    InsertCourse(N, K);//按姓名倒序,将学生的选课记录插入相应链表
    Output(K);//对K门课,输出选课学生名单
    return 0;
}

void Read_and_Sort(int *N, int *K){
    scanf("%d%d\n",N, K);
    Student = malloc(sizeof(struct StudentNode)*(*N));//学生记录
    Course = malloc(sizeof(struct CourseNode)*(*K));//课程链表表头
    for(int i=0;i<(*K);i++){//初始化课程链表表头
        Course[i].Counter = 0;
        Course[i].Ptr = NULL;
    }
    for(int i=0;i<(*N);i++){//读入并存储数据
        scanf("%s %d",Student[i].Name, &Student[i].nC);
        for(int j=0;j<Student[i].nC;j++)
            scanf("%d",&Student[i].C[j]);
    }
    qsort(Student, (*N), sizeof(struct StudentNode), CmpName);//按学生姓名排序
}

List NewNode(char *name){
    List temp;
    temp = (List)malloc(sizeof(struct ListNode));
    strcpy(temp->Name, name);
    temp->Next = NULL;
    return temp;
}

void InsertCourse(int N, int K){
    List Node;
    int CourseIndex;//暂存选课编号
    for(int i=N-1;i>=0;i--)//按姓名倒序//倒着插在表头,最后插入的表头一定是字典序最前面的
        for(int j=Student[i].nC-1;j>=0;j--){//对该生选的每门课
            CourseIndex = Student[i].C[j] - 1;//记录课程编号
            Node = NewNode(Student[i].Name);//建立新节点
            Node->Next = Course[CourseIndex].Ptr;//插入链表表头
            Course[CourseIndex].Ptr = Node;
            Course[CourseIndex].Counter++;
        }
}

void Output(int K){
    List Ptr;
    for(int i=0;i<K;i++){
        printf("%d %d\n",i+1, Course[i].Counter);
        for(Ptr=Course[i].Ptr;Ptr;Ptr=Ptr->Next)
            printf("%s\n",Ptr->Name);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_bound

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值