5. 出书最多
假定图书馆新进了m(10 ≤ m ≤ 999)本图书,它们都是由n(1 ≤ n ≤ 26)个作者独立或相互合作编著的。假设m本图书编号为整数(1到999),作者的姓名为字母('A'到'Z'),请根据图书作者列表找出参与编著图书最多的作者和他的图书列表。
时间限制:1000 内存限制:65536
输入
第一行为所进图书数量m,其余m行,每行是一本图书的信息,其中第一个整数为图书编号,接着一个空格之后是一个由大写英文字母组成的没有重复字符的字符串,每个字母代表一个作者。输入数据保证仅有一个作者出书最多。
输出
输出有多行: 第一行为出书最多的作者字母;
第二行为作者出书的数量; 其余各行为作者参与编著的图书编号(按输入顺序输出)。
样例输入
11
307 F
895 H
410 GPKCV
567 SPIM
822 YSHDLPM
834 BXPRD
872 LJU
791 BPJWIA
580 AGMVY
619 NAFL
233 PDJWXK
样例输出
P
6
410
567
822
834
791
233
【分析】
此题出现在2021年12月C语言二级考试中,出现在最后一题是在二级中相对较难的题目,需要考生耐心分析。
输入数据是每本书,以及每本书对应的作者名。此题中,有多本书和多个作者,他们的对应关系可能是:
存在一书对应多个作者,一个作者又对应多本书,是一种【多对多】的关系。
已知的是书号,以及相关联的作者,而输出则要求:输出书目最多的作者,关联的所有书号。
恰巧作者的名字都是字符,且选自26个大写字母,根据大写字母的有序性,我们考虑创建数组,作者名对应数组的下标,数组存储书号。但因为一名作者对应多个书号,所以仅仅是每位作者关联的书号,就需要一个一维数组存储,所以可以考虑二维数组 或者 结构体 完成作者书号的存储。
方案一:创建作者类型结构体
① 作者的结构体类型创建时,顺便定义了作者数组 au[ ] 。
struct Author //定义作者类型结构体
{
int num; //num:关联书的数量
int book[1000]; //book[]:存储关联的书号
} au[26];
要明确作者名和下标的对应关系:
名为 'A' 的作者信息,存入 au[ 0 ] 中;
名为 'B' 的作者信息,存入 au[ 1 ] 中;
名为 'C' 的作者信息,存入 au[ 2 ] 中;
……
名为 'X' 的作者信息,存入 au[ 'X' - 'A' ] 中;
② 接下来用输入数据给 au[ ] 数组赋值,将每本书号,放入到其关联的作者 拥有的 book[ ] 数组中。
③ 寻找书目最多的作者下标;
④ 按输出格式,打印该作者的相关信息。
#include<stdio.h>
struct Author //定义作者类型结构体
{
int num; //num:关联书的数量
int book[1000]; //book[]:存储关联的书号
} au[26];
int main()
{
int n, i, j, k, maxAu=0; //k: 临时存书号 ; maxAu 书最多的作者编号
char s[27]; //s[]: 临时存储输入字符串
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %s", &k, s);
for(j=0;s[j]!='\0';j++)
{
au[s[j]-'A'] . num++; //给作者关联书号,收获书号+1
au[s[j]-'A'] . book[ au[s[j]-'A'].num ] = k;
}
}
for(i=0;i<26;i++) //寻找书目最多的作者
{
if(au[i].num > au[maxAu].num)
maxAu = i;
}
printf("%c\n",maxAu+'A');
printf("%d\n",au[maxAu].num);
for(j=1; j<=au[maxAu].num; j++)
printf("%d\n", au[maxAu].book[j] );
return 0;
}
方案二:创建二维数组,存储每个作者的书目
经过前面的分析,我们可以创建二维数组,将每位作者关联的书号存一行,行下标对应作者的名字。
'A' 作者的信息存在第 0 行;
'B' 作者的信息存在第 1 行;
'C' 作者的信息存在第 2 行;
……
'X' 作者的信息则存在第 'X' - 'A' 行。
在读取输入数据的过程中,完成对二维数组的赋值。
以下是参考程序,和上面的结构体方案多有相似之处。
#include<stdio.h>
int author[26][100]; // 作者数组,每一行存储一个作者的书目
int main()
{
int n, i, j, k, m, maxAu=0, max=0; //k: 临时存书号 ; maxAu:书最多的作者编号;max:最大的数量
char s[27]; //s[]: 临时存储输入字符串
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %s", &k, s);
for(j=0;s[j]!='\0';j++)
{
m=0;
while(author[s[j]-'A'][m]!=0) m++; //寻找下一个书号存放位
author[s[j]-'A'][m] = k; //将书号分配给第 j 个作者
}
}
for(i=0;i<26;i++) //寻找书目最多的作者
{
m=0;
while(author[i][m]!=0) //计算当前作者的书目数
m++;
if(m > max)
{
maxAu = i;
max = m;
}
}
printf("%c\n",maxAu+'A');
printf("%d\n",max);
for(j=0; j<max; j++)
printf("%d\n", author[maxAu][j]);
return 0;
}
方案三:创建书目结构体存储作者信息
此方案是学生的探索方案,以书为结构体对象,存储每本书的 编号、关联作者;
struct Book {
int num;
char writer[300];
}book[999];
将输入数据存储在 结构体数组 book[ ] 中;
接下来的寻找出书最多的作者,则需要遍历 book 中的 writer[ ] 数组,分别计算每一位作者关联的图书数量,记录最大关联数 和 作者名 。
思路上非常清晰,但麻烦最后一步,在输出关联书目的时候,还要遍历一次整个 book 中的 writer[ ] 数组。
#include <stdio.h>
#include <string.h>
struct Book {
int num;
char writer[300];
} book[999];
int main( ) {
int m,i,j,xb,large;
char large2;
int flag[26]={0};
scanf("%d",&m);
for(i=0;i<m;i++)
scanf("%d %s",&book[i].num,&book[i].writer);
for(i=0;i<m;i++){
for(j=0;j<strlen(book[i].writer);j++)
flag[book[i].writer[j]-65]++;
}
large=flag[0];
for(i=0;i<26;i++)
if(flag[i]>large){
xb=i;
large=flag[i];
}
large2=xb+65;
printf("%c\n%d\n",large2,large);
for(i=0;i<m;i++)
for(j=0;j<strlen(book[i].writer);j++)
if(book[i].writer[j]==large2) {
printf("%d\n",book[i].num);
break;
}
return 0;
}