数据结构课设-教学计划安排-拓扑排序

数据结构课设-教学计划安排-拓扑排序

学院要求对每个专业的学生制定完备的教学计划,教学计划由课程组成,课程之间会有先后依赖关系(例如必须先学完《程序设计语言》后才能学习《数据结构》),假定每门课程需要一个学期学完,同一个学期可学习多门课程。请设计存储结构存储所有课程及其之间的依赖关系,并在此存储结构基础上完成如下操作:

\1. 输入并保存课程及课程之间的依赖关系。

\2. 判断课程能否顺利学完,若能,输出一个正确的学习顺序。

\3. 求学完这些课程最少需要几个学期,并给出一个初步的教学计划(每个学期学习哪几门课程)。

\4. 由于学生精力的限制,学校对每学期选课数的上限进行了约束,请判断约束后学生能够在原来的学期数内完成学习,若不能,此时最少需要几个学期学完这些课程**(选做)**。

img

package constant;
/**
* @author guo
*/
public interface MyConstants {
   /**
    * 最大容量
    */
   int MaxInt = 20;
   /**
    * 最多学期数限制
    */
   int maxStudy = 8;
}

package pojo;

/**
* @author guo
* 边结点
*/
public class ArcNode implements Cloneable{
   public int adjVex;
   public ArcNode nextArc;

   @Override
   public Object clone(){
       ArcNode arcNode = null;
       try {
           arcNode = (ArcNode) super.clone();
       } catch (CloneNotSupportedException e) {
           e.printStackTrace();
       }
       arcNode.nextArc = (ArcNode) nextArc.clone();
       return arcNode;
   }

   public ArcNode() {
       adjVex = 0;
       nextArc = null;
   }
}

package pojo;

/**
* 课程信息
* @author guo
*/
public class Course implements Cloneable{
   private String id;
   private String name;

   public Course() {
   }

   @Override
   public Object clone() throws CloneNotSupportedException {
       Course course = null;
       try {
           course = (Course)super.clone();
       } catch (CloneNotSupportedException e) {
           e.printStackTrace();
       }
       return course;
   }

   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
}

package pojo;
import java.util.Scanner;
/**
* AOV图(课程)
* @author guo
*/
public class Graph implements Cloneable{
   /**
    * 顶点表
    */
   public Vnode[] adjList;
   /**
    * 边数
    */
   private int e;
   /**
    * 顶点数
    */
   private int n;
   public Graph(int number,int edge) {
       adjList = new Vnode[number];
       n = number;
       e = edge;
   }
   @Override
   public Object clone() {
       Graph graph = null;
       try {
           graph = (Graph) super.clone();
       } catch (CloneNotSupportedException e) {
           e.printStackTrace();
       }
       graph.adjList = (Vnode[])adjList.clone();
       return graph;
   }

   public void setN(int n) {
       this.n = n;
   }

   /**
    * 查找顶点位置
    */
   public int locateVex(Course c){
       for (int i = 0; i < n; i++) {
           if (adjList[i].getData().getId().equals(c.getId())) {
               return i;
           }
       }
       return -1;
   }

   /**
    * 建立有向图的邻接表
    */
   public void creatAdj(){
       Scanner scanner = new Scanner(System.in);
       for (int i = 0; i < n; i++) {
           //录入顶点信息
           System.out.println("请输入课程编号");
           String id = scanner.next();
           System.out.println("请输入课程名字");
           String name = scanner.next();
           Course c = new Course();
           c.setId(id);
           c.setName(name);
           adjList[i] = new Vnode();
           adjList[i].setIn(0);
           adjList[i].setData(c);
           adjList[i].setFirstArc(null);
       }
       System.out.println("输入依赖信息:");
       for (int i = 0; i < e; i++) {
           System.out.println("请输入第"+(i+1)+"条边的两个端点,端点间使用空格间隔即可");
           String str1 =  scanner.next();
           String str2 =  scanner.next();
           Course c1 = new Course();
           Course c2 = new Course();
           c1.setId(str1);
           c2.setId(str2);
           int a = locateVex(c1);
           int b = locateVex(c2);
           if (a >= 0 && b >= 0){
               ArcNode s = new ArcNode();
               s.adjVex = b;
               s.nextArc = adjList[a].getFirstArc();
               adjList[a].setFirstArc(s);
               adjList[b].setIn(adjList[b].getIn()+1);
           }
       }
   }
}

package pojo;
import static constant.MyConstants.MaxInt;
/**
* @author guo
*/
public class Stack {
   /**
    * 用于存储课程的数组
    */
   public Course[] stackArray;
   /**
    * 栈顶指针
    */
   public int top;

   public Stack() {
       top = -1;
       stackArray = new Course[MaxInt];
   }
   public Stack(int n){
       top = -1;
       stackArray = new Course[n];
   }
   public void push(Course course){
       if (top == stackArray.length-1){
           Course[] p = new Course[top*2+2];
           for (int i = 0; i <= top; i++) {
               p[i] = stackArray[i];
           }
           stackArray = p;
       }
       top++;
       stackArray[top] = course;
   }

   public Course pop(){
       if (top == -1){
           System.out.println("栈已空,无法再删除元素!");
           return null;
       }
       top--;
       return stackArray[top+1];
   }
}

package pojo;

/**
 * @author guo
 * 点结点
 */
public class Vnode implements Cloneable{
    /**
     * 入度域
     */
    private int in;
    /**
     * 数据域
     */
    private Course data;
    /**
     * 指针域
     */
    private ArcNode firstArc;

    public Vnode(){
        in = -1;
        data = null;
        firstArc = null;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        Vnode vnode = null;
        try {
            vnode = (Vnode)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        vnode.in = ((Vnode)vnode.clone()).getIn();
        vnode.data = (Course)data.clone();
        vnode.firstArc = (ArcNode)firstArc.clone();
        return vnode;
    }
    public int getIn() {
        return in;
    }

    public void setIn(int in) {
        this.in = in;
    }

    public Course getData() {
        return data;
    }

    public void setData(Course data) {
        this.data = data;
    }

    public ArcNode getFirstArc() {
        return firstArc;
    }

    public void setFirstArc(ArcNode firstArc) {
        this.firstArc = firstArc;
    }
}

package test;

import pojo.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import static constant.MyConstants.maxStudy;

/**
 * @author guo
 */
public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入课程总数和课程依赖边数");
        System.out.println("顶点数:");
        int number = scanner.nextInt();
        System.out.println("依赖边数:");
        int edge = scanner.nextInt();
        Graph graph = new Graph(number,edge);
        //创建AOV无环网
        graph.creatAdj();
        System.out.println("输入1:题目一:判断课程能否顺利学完,若能,输出一个正确的学习顺序");
        System.out.println("输入2:题目二:求学完这些课程最少需要几个学期,并给出一个初步的教学计划(每个学期学习哪几门课程)");
        System.out.println("输入3:题目三:由于学生精力的限制,学校对每学期选课数的上限进行了约束,请判断约束后学生能够在原来的学期数内完成学习,若不能,此时最少需要几个学期学完这些课程(选做)");
        System.out.println("请输入指令:");
        int x = scanner.nextInt();
        switch (x){
            case (1):
                topSort1(graph);
                break;
            case (2):
                topSort2(graph);
                break;
            case (3):
                topSort3(graph);
                break;
            default:
                return;
        }
        scanner.close();
    }

    /**
     * 学习顺序
     * @param graph
     */
    public static void topSort1(Graph graph){
        //建立空栈,用于存放入度为0的点
        Stack stack = new Stack();
        stack.top = 0;
        int count = 0;
        //对邻接表进行遍历,将其中度为0的点压入栈中
        for (int i = 0; i < graph.adjList.length-1; i++) {
            if (graph.adjList[i].getIn() == 0){
                stack.push(graph.adjList[i].getData());
            }
        }
        System.out.println("学习顺序为:");
        while (stack.top!=0){
            //出栈并输出一个元素
            Course course = stack.pop();
            System.out.print(course.getId()+":"+course.getName());
            count++;
            //所有与其有关系的点的入度均减一
            ArcNode p = graph.adjList[graph.locateVex(course)].getFirstArc();
            while (p != null){
                int in = graph.adjList[p.adjVex].getIn()-1;
                graph.adjList[p.adjVex].setIn(in);
                //若入度减一后存在顶点的度减少为0,便将其入栈
                if (graph.adjList[p.adjVex].getIn() == 0){
                    stack.push(graph.adjList[p.adjVex].getData());
                }
                p = p.nextArc;
            }
            if (count!=graph.adjList.length){
                System.out.print("->");
            }
        }
        //出栈的元素数量小于顶点表的长度时,则表明有环产生
        if (count < graph.adjList.length){
            System.out.println("有回路产生,即无法全部学完所有课程");
        }
        System.out.println();
    }

    /**
     * 教学顺序
     * @param graph
     */
    public static void topSort2(Graph graph){
        //建立空栈,用于存放入度为0的点
        Stack stack = new Stack();
        stack.top = 0;
        int count = 0;
        int day = 0;
        //对邻接表进行遍历,将其中度为0的点压入栈中
        for (int i = 0; i < graph.adjList.length-1; i++) {
            if (graph.adjList[i].getIn() == 0){
                stack.push(graph.adjList[i].getData());
            }
        }
        while (stack.top!=0){
            //使用ArrayList集合来存储每次栈中的元素
            List<Course> list = new ArrayList<Course>();
            //将所有度为零的元素全部出栈
            while (stack.top!=0){
                Course course = stack.pop();
                list.add(course);
                count++;
            }
            day++;
            System.out.println("第"+day+"个学期的学习:");
            for (Course c : list) {
                System.out.print(c.getId()+" "+c.getName()+" ");
            }
            System.out.println();
            for (int i = 0; i < list.size(); i++) {
                ArcNode p = graph.adjList[graph.locateVex(list.get(i))].getFirstArc();
                //所有与其有关系的点的入度均减一
                while (p != null){
                    graph.adjList[p.adjVex].setIn(graph.adjList[p.adjVex].getIn()-1);
                    //若入度减一后存在顶点的度减少为0,便将其入栈
                    if (graph.adjList[p.adjVex].getIn() == 0){
                        stack.push(graph.adjList[p.adjVex].getData());
                    }
                    p = p.nextArc;
                }
            }
        }
        //若循环结束后day值大于学期最大值常数,则表明无法再大学期间学完所有课程
        if (day>maxStudy){
            System.out.println("不能在大学四年8个学期内学完");
        }else {
            System.out.println("以上为初步教学顺序");
        }
    }

    /**
     * 选课上限限制
     * @param graph
     */
    public static void topSort3(Graph graph){
        Stack stack = new Stack();
        int limit = 0;
        stack.top = 0;
        int day = 0;
        Scanner scanner = new Scanner(System.in);
        System.out.println("请设置选课上限:");
        limit = scanner.nextInt();
        //对邻接表进行遍历,将其中度为0的点压入栈中
        for (int i = 0; i < graph.adjList.length-1; i++) {
            if (graph.adjList[i].getIn() == 0){
                stack.push(graph.adjList[i].getData());
            }
        }
        while (stack.top!=0){
            int count = 0;
            List<Course> list = new ArrayList<Course>();
            //使用集合存储出栈的元素,但出栈和加入集合的元素数量应小于limit且栈不为空
            while (stack.top!=0 && count < limit){
                Course course = stack.pop();
                list.add(course);
                count++;
            }

            day++;
            System.out.println("第"+day+"个学期的学习:");
            for (Course c : list) {
                System.out.print(c.getId()+" "+c.getName()+" ");
            }
            System.out.println();
            for (int i = 0; i < list.size(); i++) {
                ArcNode p = graph.adjList[graph.locateVex(list.get(i))].getFirstArc();
                //所有与其有关系的点的入度均减一
                while (p != null){
                    graph.adjList[p.adjVex].setIn(graph.adjList[p.adjVex].getIn()-1);
                    //若入度减一后存在顶点的度减少为0,便将其入栈
                    if (graph.adjList[p.adjVex].getIn() == 0){
                        stack.push(graph.adjList[p.adjVex].getData());
                    }
                    p = p.nextArc;
                }
            }
        }
        //若学期数大于学期最大值常数,则表明无法在学完所有课程,并输出所有的学期以及所上的课程
        if (day>maxStudy){
            System.out.println("需要"+day+"个学期才能学完"+"不能在大学四年8个学期内学完");
        }else {
            System.out.println("以上为限制选课教学顺序");
        }
    }
}
  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
采用C++编写,完成了题目的所有要求,并附有说明文档。 大学的每个专业都要制定教学计划。假设任何专业都有固定的学习年限,每学年含两学 期,每学期的时间长度和学分上限值均相等,每个专业开设的课程都是确定的,而且课程在 开设时间的安排必须满足先修关系。每门课程有哪些先修课程是确定的,可以有任意多门, 也可以没有。每门课恰好占一个学期。试在这样的前提下设计一个教学计划编制程序。 [基本要求] (1)输入参数包括:学期总数,一学期的学分上限,每门课的课程号(固定占3位的字母数字串)、学分和直接先修课的课程号。 (2)允许用户指定下列两种编排策略之一:一是使学生在各学期中的学习负担尽量均匀;二是使课程尽可能地集中在前几个学期中。 (3)若根据给定的条件问题无解,则报告适当的信息;否则将教学计划输出到用户指定的文件中。计划的表格格式自行设计。 [测试数据] 学期总数:6;学分上限:10;该专业共开设12门课,课程号从C01到C12,学分顺序为2,3,4,3,2,3,4,4,7,5,2,3。先修关系如下: 课程编号 课程名称 先决条件 C1 程序设计基础 无 C2 离散数学 C1 C3 数据结构 C1,C2 C4 汇编语言 C1 C5 语言的设计和分析 C3,C4 C6 计算机原理 C11 C7 编译原理 C5,C3 C8 操作系统 C3,C6 C9 高等数学 无 C10 线性代数 C9 C11 普通物理 C9 C12 数值分析 C9,C10,C1 [实现提示] 可设学期总数不超过12,课程总数不超过100。如果输入的先修课程号不在该专业开设的课程序列中,则作为错误处理。应建立内部课程序号与课程号之间的对应关系。
问题描述:大学的每个专业都要制定教学计划。假设任何专业都有固定的学习年限,每学年含两个学期,每学期的时间长度和学分上限值均相等。每个专业开设的课程都是确定的,而且课程在开设时间的安排上必须满足先修关系。每门课程有哪些先修课程是确定的,可以有任意多门,也可以没有。每门课程恰好占一个学期。试在这样的前提下设计一个教学计划编制程序。 基本要求:输入参数包括学期总数,一学期的学分上限,每门课程的课程号、学分和直接先修课的课程号;允许两种策略,一是使学生在各学期的学习负担尽量均匀,二是使课程尽量集中在前几个学期;若根据给定的条件问题无解,则报告适当的信息,否则输出教学计划表(如每个学期所开设的课程的课程号及学分),同时将教学计划输出到用户指定的文件中。教学计划的表格格式自行设定, 可以从键盘读取数据也可以从文件读取数据, 结果保存到文件中。 测试数据:学期总数为6,学分上限为10,该专业共开设12门。以10级某专业必修课与选修课为例,选择12门课程及相应学分,制定一个表明各门课程先后约束关系的有向图。 提高要求:产生多种不同的方案,并使方案之间的差异尽可能地大。 考核要求: (1)达到基本要求,成绩为良好,如果不能把结果保存到文件中,成绩为不及格。 (2)在达到基本要求的基础上,产生3种以上的解决方案,且用户界面友好,成绩为优秀。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值