STL-vector,map,set集合应用案例

2022-06-16 15:09:58 浏览数 (1)

具体案例:

学校需要将不同学科的学生分配到一组。每个学生都必须学习指定的最小数目的学科。每个学习特定学科的学生都被保存到 set容器中,因为一个学生只能在一门特定课程中出现一次。

基本流程:

第一步:学生类

代码语言:javascript复制
  #ifndef STUDENT_H
    #define STUDENT_H
    #include <string>                                
    #include <ostream>    

    //两个成员函数,保存姓,名                        
    class Student
    {
        private:
            std::string first {};
            std::string second {};
        public:
            Student(const std::string& name1, const std::string& name2) : first (name1), second (name2){}
            //移动构造
            Student(Student&& student) : first(std::move(student.first)),
                             second(std::move(student.second)){}
            //复制构造
            Student(const Student& student) : first(student.first), second(student.second){}                  // Copy constructor
            Student() {}                                                                                      // Default constructor
          
            bool operator<(const Student& student) const
            {
                return second < student.second || (second == student.second && first < student.first);
            }
            //友元函数重载了一个流插入运算符来辅助输出
            friend std::ostream& operator<<(std::ostream& out, const Student& student);
    };
    
    inline std::ostream& operator<<(std::ostream& out, const Student& student)
    {
        out << student.first   " "   student.second;
        return out;
    }
    #endif

第二步:输出类

代码语言:javascript复制
#ifndef LIST_COURSE_H
    #define LIST_COURSE_H
    #include <iostream>                          
    #include <string>                              
    #include <set>                              
    #include <algorithm>                          
    #include <iterator>                        
    #include "s.h"

    using Subject = std::string;                  
    
    using Group = std::set<std::weak_ptr<Student>, std::owner_less<std::weak_ptr<Student>>>;  
    
    using Course = std::pair<Subject, Group>;      
    
    class List_Course
    {
    public:
        void operator()(const Course& course)
        {
            std::cout << "nn" << course.first << "  " << course.second.size() << " students:n  ";
            std::copy(std::begin(course.second), std::end(course.second),
                         std::ostream_iterator<std::weak_ptr<Student>>(std::cout, "  "));
        }
    };
    inline std::ostream& operator<<(std::ostream& out, const std::weak_ptr<Student>& wss)
    {
        out << *wss.lock();
        return out;
    }
    #endif

第三步:主函数

代码语言:javascript复制
    #include <iostream>                        
    #include <string>                                
    #include <map>                                  
    #include <set>                                
    #include <vector>                                
    #include <random>                              
    #include <algorithm>            // For for_each(), count_if()
    #include <memory>               // For shared_ptr and weak_ptr
    #include "s.h"
    #include "l.h"

    using std::string;

    using Distribution = std::uniform_int_distribution<size_t>;

    using Subject = string;              
    using Subjects = std::vector<Subject>;    
    
    //学生集合对象别名
    using Group = std::set<std::weak_ptr<Student>, std::owner_less<std::weak_ptr<Student>>>;  
    
    //定义学生类别名
    using Students = std::vector<std::shared_ptr<Student>>;    
   
    using Course = std::pair<Subject, Group>;  
    //课程容器              
    using Courses = std::map<Subject, Group>;        
   //随机数创建器
   //分布对象是一个函数对象,它可以创建分布内的随机数,可以将随机数创建器对象作为参数传给分布对象的成员函数opemtor()()
    static std::default_random_engine gen_value;
   
    // 创建对象
    Students create_students()
    {
        Students students;
        string first_names[]{"Ann", "Jim", "Eve", "Dan", "Ted"};
        string second_names[]{"Smith", "Jones", "Howe", "Watt", "Beck"};
        for(const auto& first : first_names)
            for(const auto& second : second_names)
            {
                students.emplace_back(std::make_shared<Student>(first, second));
            }
        return students;
    }

    // 为指定学科随机创 建一组学生
    //第一个参数是一个包含 Student 对象的 vector,第二个参数是组中要求的学生个数,
    //最后一个参数是分布的索引值,用来选择随机创建的学生
    Group make_group(const Students& students, size_t group_size,
                                          Distribution& choose_student)
    {
        Group group;  
        size_t count{};                  
        std::pair<Group::iterator, bool> pr;  
        
        while(count < group_size)
        {  //如果插入的元素已经在容器中,成员函数 insert() 不会插入新的对象。
            
          pr=group.insert(students[choose_student(gen_value)]);//???????????????????
            if(pr.second)
                  count;
        }
        //会通过移动而不是复制的方式返回局部的 group 对象
        return group;
    }


    int main()
    {
        Students students = create_students();
        //学科定义
        // subjects 是一个包含 string 对象的 vector 容器。
        Subjects subjects {"Biology", "Physics", "Chemistry", "Mathematics",
                            "Astronomy","Drama", "Politics", "Philosophy", "Economics"};
       //一个包含全部课程的容器
        Courses courses;     //pair<string,set<>>    
        
         //需要学习的最少学科数
        size_t min_subjects{4};    
        //每组的最少学生数都设为相同的 值
        size_t min_group{min_subjects};  
        //每个学科组的最大学生数就是一个平均值
        size_t max_group{(students.size()*min_subjects) / subjects.size()};

        //一个用来在均匀分布中选择随机值的函数对象:
        //创建 min_group〜max_group 范围内的随机数
        Distribution group_size{min_group, max_group};
        //创建students中的有效索引值。
        Distribution choose_student{0, students.size() - 1};  
        
        //为 course 容器填充了一些表示课程信息的元素
        for(const auto& subject : subjects)
            courses.emplace(subject, make_group(students, group_size(gen_value), choose_student));

        //创建 subjects 容器的一个有效索引值,可以用它来选择课程
        Distribution choose_course{0, subjects.size() - 1};    

      //检查每个学生是否都选了足够的课程
      //如果没有选择足够的课程,为他们申请其他的课程
        for(const auto& student : students)
        {    
            //count_if() 算法用来计算每个学生已报名参加的课程数
            //count_if() 的第三个参数必须是一个二元函数,它的返回值必须是布尔值或其他可以隐式转换为布尔型的值
            size_t course_count = std::count_if(std::begin(courses), std::end(courses),
                         [&student](const Course& course)
            {  return course.second.count(student); });

            if(course_count >= min_subjects)
                    continue;            
    
            size_t additional{min_subjects - course_count};      
            if(!course_count)                                      
                std::cout << *student << " is work-shy, having signed up for NO Subjects!n";
            else                                                
                std::cout << *student << " is only signed up for " << course_count << " Subjects!n";

            std::cout << "Registering " << *student << " for " << additional
                  << " more course" << (additional > 1 ? "s" : "") << ".nn";
            //为这些学生申请新的课程,直到他们申请的课程数目满足要求
            while(course_count < min_subjects)
                if((courses.find(subjects[choose_course(gen_value)])->second.insert(student)).second)
                           course_count;
        }
        // 输出课程
        std::for_each(std::begin(courses), std::end(courses), List_Course());
        std::cout << std::endl;
    }

结果显示:


0 人点赞