前言
《算法笔记》vector的使用
一、题目分析
具体题目见:http://codeup.hustoj.com/problem.php?cid=100000596&pid=0 大致题意:给定所有课程的学生名单和需要查询的学生名单,输出查询学生的课程表。
二、 需求分析
1.输入分析
每个输入文件一个测例。 第一行输入两个整数,查询课表的学生人数N(<=4000)和课程总数K(<=2500)。 接下来输入所有课程的学生名单,对每个课程来说,首先一行输入课程索引i和该门课的学生人数Ni(<=200),下一行输入该门课的学生名单。 最后输入查询课表的N个学生名字,每个学生的名字前面是三个大写字母,后面是一位数字。 每一行的数字和名字之间由一个空格分隔。
2.输出分析
共输出N行,每行对应一个学生,每行输出学生的名字、该学生的课程总数及其索引的升序排列。
3.功能分析
(1)输入课程的学生名单 (2)进行学生课表的查询 (3)输出学生课表
4.测试数据
输入数据:
11 5
4 7
BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
1 4
ANN0 BOB5 JAY9 LOR6
2 7
ANN0 BOB5 FRA8 JAY9 JOE4 KAT3 LOR6
3 1
BOB5
5 9
AMY7 ANN0 BOB5 DON2 FRA8 JAY9 KAT3 LOR6 ZOE1
ZOE1 ANN0 BOB5 JOE4 JAY9 FRA8 DON2 AMY7 KAT3 LOR6 NON9
输出数据:
ZOE1 2 4 5
ANN0 3 1 2 5
BOB5 5 1 2 3 4 5
JOE4 1 2
JAY9 4 1 2 4 5
FRA8 3 2 4 5
DON2 2 4 5
AMY7 1 5
KAT3 3 2 4 5
LOR6 4 1 2 4 5
NON9 0
三、概要设计
1.数据结构
名字有限制,总共只有26 * 26 * 26 * 10个,名字可以映射为整数,使用整数保存即可。(散列hash) 每个学生选的课程使用二维整数数组存储,第一维学生,第二维是其所选的课程。
2.基本操作
基本操作 | 操作结果 |
---|
name_to_id() | 把字符名字映射成整数id | get_course_list() | 输入课程的学生名单并求出每个学生的课表 | put_course_list() | 输出进行查询的学生的课表 |
3.程序模块及调用图
(1)程序包含如下模块:
- 主程序模块 main()
- 名字映射模块 name_to_id()
- 课表输入模块 get_course_list()
- 课表输出模块 put_course_list()
(2)模块调用图
四、详细设计
1.数据结构
学生课表的存储使用二维数组,第一维存储名字id,维数大小至少为26 * 26 * 26 * 10。第二维存储学生的课程,维数不确定,使用vector,大小可以通过size()获取。
2.各模块设计
(1)主程序模块
主程序依次调用课表输入模块和课表输出模块即可。
(2)课表输入模块
在输入每门课程的学生名单时,调用名字映射模块得到整数id,将该课程添加到课表中。
(3)课程输出模块
输入需要查询课表的学生名单,调用名字映射模块得到其在课表中的位置。使用sort排序,大小调用内置操作size()可以获得,vector的访问可以通过下标或迭代器,按输出要求格式进行输出。
(4)名字映射模块
将26 * 26 * 26 * 10个名字映射到0~ (26 * 26 * 26 * 10-1)范围内。 名字前三位减去字符‘A’,后一位减去字符’0‘ C1C2C3C4 hash(C1C2C3C4)=C1 * 262 * 10+C2 * 26 * 10+C3 * 10 +C4=((C1*26+C2) *26+C3) *10+C4
五、代码实现
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=26*26*26*10;
vector <int> course_list[maxn];
int name_to_id(char* name){
int id=0;
int i;
for(i=0;i<3;i++){
id=id*26+(name[i]-'A');
}
id = id * 10 + (name[3] - '0');
return id;
}
void get_course_list(int num){
int course_index,students;
while(num--){
scanf("%d %d",&course_index,&students);
while(students--){
char name[5];
scanf("%s",name);
int id=name_to_id(name);
course_list[id].push_back(course_index);
}
}
}
void put_course_list(int num){
char name[5];
while(num--){
scanf("%s",name);
int id=name_to_id(name);
sort(course_list[id].begin(),course_list[id].end());
printf("%s %d",name,course_list[id].size());
vector <int>::iterator it=course_list[id].begin();
for(;it!=course_list[id].end();it++){
printf(" %d",*it);
}
printf("\n");
}
}
int main(){
int N,K;
scanf("%d %d",&N,&K);
get_course_list(K);
put_course_list(N);
return 0;
}
六、总结
- vector已经实现了较高程度的封装,在使用过程中可以只考虑数据的操作过程,不需要考虑数组的规模等,要熟悉其内置操作。
- vector的begin()、end()和迭代器都是地址。
- 字符串hash可以加快程序的运行速度,需要掌握。
- sort函数在头文件algorithm中。
|