结对第二次作业

本文介绍了一个基于学生和部门数据的智能匹配算法实现案例,重点在于如何根据学生意愿、空闲时间等因素与部门需求进行高效匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高级软工结对第二次作业

github项目地址

需求分析

本次结对项目对最终程序的功能要求如下:

编码实现一个部门与学生的智能匹配的程序。
实现一个智能自动分配算法,根据输入信息,输出部门和学生间的匹配信息(一个学生可以确认多个他所申请的部门,一个部门可以分配少于等于其要求的学生数的学生) 及未被分配到学生的部门未被部门选中的学生

本项目的关键在于设计一个智能匹配算法,该算法主要实现根据输入的学生和部门数据,输出符合部门要求的匹配名单。现从部门角度做出如下需求分析:

  • 优先考虑将本部门作为第一部门意愿的学生
  • 优先考虑空闲时间段和本部门常规活动时间段相符程度大的学生
  • 综合考虑学生空闲时间与本部门常规活动时间符合度、兴趣标签与本部门特点标签符合度、绩点高低

数据模型

模型的分析与建立

根据需求分析建立如下数据模型:

  • 部门数据模型:
字段数量(个)类型
部门名称1字符
人数上限1数值
特点标签1-5字符
常规活动时间1-5字符
录取学生名单1字符

注:其中录取学生名单 字段取值由匹配算法产生

部门数据模型样例:

部门名称人数上限特点标签常规活动时间录取学生名单
活动部14看电影,跳舞Sun,20:30,21:00;Tue,19:30,20:00;Fri,20:30,23:00沈剑伸,杨伸世
  • 学生数据模型:
字段数量(个)类型
学号1字符
姓名1字符
绩点1数值
意愿部门1-5字符
意愿部门数1数值
未匹配意愿数1数值
兴趣标签1-5字符
空闲时间1-5字符
各部门综合得分1-20数值

注:其中意愿部门数未匹配意愿数各部门综合得分 字段取值由匹配算法产生

学生数据模型样例:

学号姓名绩点意愿部门意愿部门数未匹配意愿数兴趣标签空闲时间各部门综合得分
170312369沈剑伸1.07策划部,权益部,客服部,外联部40策划,乒乓球,学习Fri,22:30,23:30;Sat,19:30,20:0025.07,30,26,28

注:由于时间段为随机产生,为避免部门常规时间与所有学生的空闲时间都无法匹配的情况,将时间段限制在19:00-23:00

代码规范

规定在编程过程中须严格遵循以下规范:

  • 对于代码的各个功能和参数进行了详细注释
  • 变量以及函数命名的规范:使用驼峰命名法进行命名
  • 使用类来封装面向对象的概念

代码佐证如下:

class Department
{
public:
    Department(string name, string limitNum, string feature, string normalDate)
    {
        setLimitNum(limitNum);
        setFeature(feature);
        setNormalDate(normalDate);
        setName(name);
    }
private:
    string name;   //部门名称
    int limitNum;  //人数上限
    int existing;  //已选人数
    vector<string> feature; //特点标签
    vector<vector<float>> normalDate;    //常规活动时间
    vector<Student> stuList;//创建被录取学生名单
public:
    void setLimitNum(string limitNum);
    void setExisting();
    void setFeature(string feature);
    void setNormalDate(string normalDate);
    void addMember();
    void setName(string name);
    string getName();
    int getExisting();
    int getLimitNum();
    vector<vector<float>> getNormalDate();
    vector<string>getFeature();
    friend vector<float> timeCut(string normalDate);
    friend vector<string> slice(string s, const char* b);
    void setStu(Student s);
    vector<Student> getStu();
};

匹配算法

算法描述

  • 遍历所有学生的第i(1-5)志愿部门并计算第一志愿对应的部门综合得分
  • 以第i(1-5)志愿得分为依据进行降序排序后进行录取(将录取学生加入录取学生名单)
  • 循环执行以上步骤直到所有部门录取人数达到上限(每个部门最多15人)或所有学生志愿(每个学生最多5个)均已计算过得分

算法流程如下图:

1249576-20171026202038945-269585299.png

算法分析

本算法结合部门需求,从实际出发,模拟现实生活中部门招新过程,即每个部门最先匹配的是第一志愿填报本部门的学生,根据学生信息进行评估录取,若录取人数未达到上限则进行第二轮录取,即开始遍历学生的第二志愿。即考虑以下两条原则:

  • 志愿优先
  • 综合得分优先

关键代码

匹配算法的关键代码如下:

void Match::start()
{
    //遍历5个志愿
    for (int i = 0; i < 5; i++)
    {
        //学生对象遍历
        vector<Student>::iterator stuIter = stu.begin();
        while (stuIter != stu.end())
        {
            //匹配学生第i志愿部门,进行对应的匹配评分
            string intent = stuIter->getIntentDepart()[i];
            if (intent == "")
            {
                stuIter->setNotMatch();
                matchOver.push_back(*stuIter);
                stuIter = stu.erase(stuIter);
                continue;
            }
            vector<Department>::iterator Iter = dep.begin();
            //查找到学生第i志愿部门对象
            while (Iter != dep.end())
            {
                Iter->getName();
                if (Iter->getName() == intent)
                {
                    break;
                }
                Iter++;
            }
            //将绩点作为成绩的一部分算入匹配分数
            stuIter->changeMark(intent, stuIter->getGpa());
            //如果学生空闲时间和部门活动时间完全不匹配则分数归零,匹配下一学生的志愿
            timeMatch(*stuIter, *Iter);

            //匹配兴趣标签并打分
            tagMatch(*stuIter, *Iter);
            //学生未匹配志愿减一
            stuIter->setNotMatch();
            stuIter++;
        }
        vector<Department>::iterator depIter = dep.begin();
        //在第i个志愿下,按照不同部门对学生分别进行分数排序,取出每个部门对应的成绩非零的同学加入部门
        while (depIter != dep.end())
        {
            order(stu, depIter->getName());
            stuIter = stu.begin();
            while (stuIter != stu.end())
            {
                if (depIter->getExisting() == depIter->getLimitNum() || !stuIter->getMark(depIter->getName()))
                {
                    stuIter++;
                    continue;
                }
                depIter->setStu(*stuIter);
                stuIter->setMarkZero(depIter->getName());
                depIter->setExisting();
                stuIter->setAccess();
                //如果学生所有志愿完成匹配,则转移学生对象至matchOver容器
                if (!stuIter->getNotMatch())
                {
                    matchOver.push_back(*stuIter);
                    stuIter = stu.erase(stuIter);
                }
                else
                {
                    stuIter++;
                }
            }
            depIter++;
        }
    }
}

结果分析评价

测试报告

根据以上算法形成的算法测试报告如下:

优先条件匹配学生个数未匹配学生个数实际耗时(s)输出文件路径
志愿优先19210829.313文件路径

性能分析

1249576-20171026215001461-2023935318.jpg

性能分析结果如上图所示,排序占用了93.60%的时间,不出意外的占用了大部分时间,因为这里采用了冒泡排序的方法。如果改进排序方法,程序性能可能取得进一步的提升。

结果分析

该算法对于不同优先条件变更的适应能力很好,对于不同的优先条件,我们只需要调整对应条件的评分权重,使该条件的得分足够大即可,所以改动也只需要几分钟而已。

结对感受

林翔的结对感受

林翔的结对感受:本次的作业极大的锻炼了我的代码能力。在与李明皇的结对过程中,感受到了他的认真严谨的态度。在设计算法模型和敲代码时我们经常发生争论,但是最后都能很好的解决问题。

李明皇的结对感受

本次结对项目所给的时间有点紧,还好这几天课比较少,不然可能完成不了。时间主要花在了算法设计和最后的debug上。
以前对C++的实践主要停留在做题的层面上,在真正的编程中发现了在题目中学不到的东西,比如代码的规范性对编程效率起到了很大的作用,好的规范会使代码review事半功倍。
队友林翔在结对编程中很给力,他的逻辑思维一直很清晰,对于整个算法的把握了然于胸,能够很快的想到我没有考虑的地方并给出解决方案。

转载于:https://www.cnblogs.com/liminghuang/p/7726901.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值