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

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

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

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

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

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

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

数据结构课设-教学计划安排-拓扑排序_第1张图片

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("以上为限制选课教学顺序");
        }
    }
}

你可能感兴趣的:(数据结构实验,数据结构,拓扑学,java,图论)