结对第二次作业
170327078 张合胜
170320075 解哲
Github地址:点我点我
数据模型
样例链接:学生数据 部门数据
部门数据根据需求主要包括了部门编号,部门纳新人数,部门喜好标签和部门活动时间。而学生数据根据需求主要包括了学号,绩点,部门志愿,个人爱好,空闲时间等。主要考虑的因素是学生的唯一性和部门唯一性还有时间与标签的表达方式。
20个部门:
部门编号:字符串(唯一);
部门纳新上限:整数;
部门特色标签:字符串向量;
部门活动时间:字符串向量;
300个学生:
学生学号:字符串(唯一);
学生绩点:浮点数[1,5];
部门志愿:字符串向量[1,5];
个人爱好:字符串向量;
空闲时间:字符串向量;
数据生成的类型主要包括以下部分:
部门编号和学号:采用从0开始的编码方式逐步增加,采用此方法的原因是学号和部门号不宜设置成随机数,因为随机数编号过于混乱。
学生绩点:此数据不需要判断重复,唯一需要注意的是随机浮点数的范围必须在征程范围【1,5】之间。
部门志愿:同一学生的部门志愿不能重复,这里需要随机生成1-5个志愿,且志愿之间不能重复。
个人爱好:这个数据类似于部门志愿,数据为1-n个标签,也不允许重复。
空闲时间:这个数据采用字符串向量储存,其中包含了1-n个空闲时间段,我们将一天分成7天,一天11节课来划分时间段,随机产生空闲时间。
部门纳新上限:范围为1-15的随机整数,用以限制数据范围。
部门活动时间:其在结构上与学生空闲时间完全相同,这主要是为了让后续比对更加方便。
数据输出格式:
这部分的工作说简单不简单,说难不难,我们小组在之前没有想过使用Json来创建TXT文件,于是我们在一番讨论之后确定了数据的生成格式。
部门格式
part0
2
2
ping-pang
opera
11
6B
3I
5K
6H
7F
2D
3C
4C
3D
3B
6F
学生格式
6245919
1.42857
2
part19
part2
4
football
basketball
opera
ping-pang
10
6B
3H
2E
4A
7B
3A
6C
6E
1A
3K
本团队的数据格式看上去很是丑陋,且意义不直观。但我们为了处理方便,只能牺牲可读性来完成数据输出。其中学生格式中第一行为学号,第二行为绩点,第三行为志愿数,第四行为志愿部门编号,第五行为爱好标签数,第六行为爱好标签,第七行为空闲时间数,第八行为空闲时间标签。其中空闲时间标签为字符串,其中字母表示星期数,数字表示第几节课。
学生部门匹配算法
数据集的建立:
对于数据的建立,我们采用了完全随机的方式,让每次的数据都不相同。且读取采用按行读取的方式,依据数据顺序提取对应的变量,最后用这些数据初始化学生类和部门类。完成数据的生成和读入。
在这一过程中,最让我们头疼的是如何读入数据,在尝试了逐词读入,逐字符读入和逐行读入后,我们选择了逐行读入并利用赋值给变量实现了数据的提取。在这部分的问题解决之后,才到本次作业的重头戏,即学生对象和部门对象的匹配。
匹配过程:
由于时间紧迫,我们先实现了绩点匹配这种匹配方式。
代码规范
变量的命名:字段之间用_连接,如name_part,num_sdt_dpt,类方法的命名和成员变量命名保持统一。
//学生类
class Student
{
public:
Student(){}
Student(string id,float grade,vector<string> interest,vector<string> sdt_dpt,vector<string> free_time)
//Student(id,grade,interest,sdt_dpt,free_time);
{
num_free_time = 0;
vector<string>::iterator iter_str;
this->grade = grade;
this->id = id;
for(iter_str = interest.begin();iter_str != interest.end();iter_str++)
{
this->interest = interest;
}
vector<string>::iterator iter_Dep;
for(iter_Dep = sdt_dpt.begin();iter_Dep != sdt_dpt.end();iter_Dep++)
{
this->sdt_dpt = sdt_dpt;
++num_sdt_dpt;
}
for(iter_str = free_time.begin();iter_str != free_time.end();iter_str++)
{
this->free_time = free_time;
++num_free_time;
}
}
vector<string> * getSdtDpt()
{
return & sdt_dpt;
}
int getNumFreeTime()
{
return num_free_time;
}
int getNumSdtDpt()
{
return num_sdt_dpt;
}
void addDepart()
{
++num_depart;
}
int numDepart()
{
return num_depart;
}
vector<string> getFreeTime()
{
return free_time;
}
float getGrade()
{
return grade;
}
string getID()
{
return id;
}
private:
float grade;//绩点
int num_depart = 0;//////////////////////////////////
int num_free_time,num_sdt_dpt = 0;
vector<string> interest;
vector<string> sdt_dpt;//学生选择部门
vector<string> free_time;//空余时间段
string id;
};
注释明确,便于求改,以下是自动生成学生信息的函数:
oid studentRandom()
{
int num_free,num_interest;
int i,j,num_will_part;
float grade;
int id;
vector<string>::iterator itr;
vector<string> vec_free,vec_interest,vec_will_part;
string free_week[7] = {"1","2","3","4","5","6","7"};
string free_class[11] = {"A","B","C","D","E","F","G","H","I","J","K"};
string label_interest[5] = {"ping-pang","football","basketball","opera","draw"};
string will_part[20]={"part0","part1","part2","part3","part4","part5","part6","part7","part8",
"part9","part10","part11","part12","part13","part14","part15",
"part16","part17","part18","part19"};
ofstream out;
out.open("student_input.txt");
for(j = 0;j < N_student;j++)
{
//生成七位数学号
id = rand() % 10000000;
while(id < 1000000 || id > 9999999)
{
id = rand() % 10000000;
}
//生成绩点
grade = (rand() % 12) / 2.8;
num_will_part = rand() % 5;//随机5个以内志愿部门
for(i = 0;i < num_will_part;i++)
{
int random = rand() % 20;//part0~part19
if(i == 0) vec_will_part.push_back(will_part[random]);
else
{
itr = find(vec_will_part.begin(),vec_will_part.end(),will_part[random]);//查询向量中有没有
if(itr != vec_will_part.end())//说明重复了
{
--i;
}
else vec_will_part.push_back(will_part[random]);
}
}
num_interest = rand() % 5;//随机5个兴趣标签
for(i = 0;i < num_interest;i++)
{
int random = rand() % 5;
if(i == 0) vec_interest.push_back(label_interest[random]);
else
{
// //随机生成一个数 与之前的数不同 生成数大小0~4 生成num_interest次
itr = find(vec_interest.begin(),vec_interest.end(),label_interest[random]);
if(itr != vec_interest.end())//说明重复了
{
--i;
}
else vec_interest.push_back(label_interest[random]);
}
}
num_free = rand() % 12;//0~11个空余时间
for(i = 0;i < num_free;i++)
{
int j = rand() % 7;
int k = rand() % 11;
string route = free_week[j] + free_class[k];
if(i == 0) vec_free.push_back(route);
else
{
itr = find(vec_free.begin(),vec_free.end(),route);
if(itr != vec_free.end())//说明与之前重复 重新进行一次随机生成空余时间
{
--i;
continue;
}
else vec_free.push_back(route);
}
}
out << id << '
';
out << grade << '
';
out << num_will_part << '
';
for(itr = vec_will_part.begin();itr != vec_will_part.end();itr++)
{
out << *itr << '
';
}
out << num_interest<< '
';
for(itr = vec_interest.begin();itr != vec_interest.end();itr++)
{
out << *itr << '
';
}
out << num_free << '
';
for(itr = vec_free.begin();itr != vec_free.end();itr++)
{
out << *itr << '
';
}
vec_free.clear();
vec_interest.clear();
vec_will_part.clear();
}
out.close();
}
结果分析评价
我们的匹配方式相对比较好的完成了用户的需求,每个部门都可以获得足够的部员,而使得未能进入部门的学生数量相对较少。这个结果大致符合我们的预期,但是如果用另外的匹配方式,可能获得更好的结果,但是由于时间的关系,我们没有对其进行对比实验。结论就是总体满足,细节还有改善空间。
总结与感受
总结
这次的作业与上次的结对作业有很大的联系,但是在我们进行第二次作业时,并没有大量使用第一次作业的成果来加速我们的工作进度。这是我们的一大失误,主要原因是对设计没有细化,没有做深入的推敲。在设计工作上的不足,加上在编码过程中的配合缺乏统一的标准,导致在代码分工上有些许的混乱。在之后的作业中,我们需要对这次作业中存在的代码风格不一致,编码进度慢等问题进行解决。
这次的作业工作量大,时间紧迫,在有限的时间里我们绞劲脑汁也很难完全满足用户需求,在文件可读性上,我们做了牺牲,用以快速读入数据。在花了一上午用来生成数据之后,我们又花了大半天来读入数据。读入数据又牵扯到文件的读入方式与字符处理。导致我们在读入数据时花费的时间还是比较多的,这也是没法避免的。
感受
这次的作业给我的感受就是难,时间短,工作量大。而对于结对成员张合胜同学,我的看法是他的编程能力强,执行力高,这次作业的核心--------匹配就是由他编码完成的。我们通过讨论明确了数据的结构,合作完成了信息的读入。但是,我们队伍之间的配合还是有一定的改善空间的,尤其是在设计上,我们的想法可以更加成熟,更加具有创新性。我很高兴我能通过这次的机会认识张合胜同学,在今后的学习生活中,我也希望能和他有更多的交流和更多向他学习的机会。