出书最多 [2021年12月 电子学会C语言编程等级考试二级真题解析]

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;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值