教学编制计划—Java
1. 问题描述
大学的每个专业都要制定教学计划。假设任何专业都有固定的学习年限,每学年含两学期,每学期的时间长度和学分上限值均相等。每个专业开设的课程都是确定的,而且课程在开设时间的安排必须满足先修关系。每门课程有哪些先修课程是确定的,可以有任意多门,也可以没有。每门课恰好占一个学期。试在这样的前提下设计一个教学计划编制程序。
2.基本要求
- 输入参数包括:学期总数,一学期的学分上限,每门课的课程号(固定占3位的字母数字串)、学分和直接先修课的课程号。
- 允许用户指定下列两种编排策略之一:一是使学生在各学期中的学习负担尽量均匀;二是使课程尽可能地集中在前几个学期中。
- 若根据给定的条件问题无解,则报告适当的信息,否则将教学计划输出到用户指定的文件中。计划的表格格式自行设计。
3.题目分析
- 首先课程与课程之间的关系是多对多的关系,在数据结构中这是属于图形结构。图的结点包括课程号、课程名、学分、先修关系这些属性。
- 其次本题的难点除了最后的平均排课和集中排课方法以外,就是将课程之间的先修关系表现出来。在图结构中,拓扑排序恰好可以表示这一关系。拓扑排序可以使用栈(排序后唯一)或者队列(多种排序结果)进行排序。以为这里不需要唯一性,所以我使用了队列。
- 最后排课的两个方法,比较容易的是集中排序,平均排序就要多下点功夫了。因为我懒~所以这里将数据保存在MySQL数据库中,这样就不用再测试时频繁的输入了,然后用Servlet 将结果发送到网页进行显示。因为程序比较简单,所以没用框架什么的。
4.类的具体实现以及结果截图
图 4-1 类的创建结果截图
图 4-2 效果截图
5.主要代码片段
//生成拓扑排序后的图,并返回
public class CreateGraph {
static Scanner scanner=new Scanner(System.in);
static int inDegree[];
//用邻接表存储图
public void initialGraph(Graph graph,MySQL mysql) {
inDegree = new int[graph.vertexNum+1];
List<Edge> temp=new ArrayList<Edge>();
//数据库读取
try {
temp=mysql.getValue();
} catch (SQLException e) {
System.out.println("引用有误");
e.printStackTrace();
}
//判断入度的个数
for(int i = 0; i < temp.size(); i++){
int u = temp.get(i).start;
int v = temp.get(i).end;
graph.vlist[u].add(v);
inDegree[v]++;
}
}
//拓扑排序
public ArrayList<Vertex> topologicalSort(Graph graph,MySQL mysql) {
ArrayList<Vertex> list=new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
//检查入度为零的顶点
for(int i = 1; i <=graph.vertexNum; i++){
if(inDegree[i] == 0){
queue.add(i);
}
}
while(!queue.isEmpty()){
int u = queue.poll();
try {
Inform inform=mysql.getinformation(u);
String vlaue=inform.value;
String name=inform.name;
int score=inform.score;
list.add(new Vertex(vlaue,name,score));
} catch (SQLException e) {
e.printStackTrace();
}
for(int i = 0; i < graph.vlist[u].size(); i++){
int v = graph.vlist[u].get(i);
inDegree[v]--;
if(inDegree[v] == 0)
queue.add(v);
}
}
return list;
}
}
// 集中排序
public Map<Integer,Object > makeFirst() {
ArrayList<Vertex> list = allList();
ArrayList<Vertex> list1 =new ArrayList<Vertex>();
//这里是存放到HashMap中,最后返回到到网页页面中
Map<Integer, Object> map = new HashMap<>(8);
int stuNum = 8;//学期数
int max = 6;//最大学分
int j = 0;//临时下标
int tol=0;
for(int i= 1 ; i <= stuNum;i++) {
while(true){
if(j<=list.size()-1) {
tol += list.get(j).score;
if(tol <= max ) {
list1.add(list.get(j));
j++;
}else {
map.put(i,list1);
tol=0;
list1=new ArrayList<Vertex>();
break;
}
}else {
break;
}
}if(j>list.size()-1) {
list1.add(new Vertex("无","无",0));
map.put(i,list1);
list1=new ArrayList<Vertex>();
j++;
}
}
return map;
}
//平均分布
public Map<Integer,Object> makeSecond() {
ArrayList<Vertex> list = allList();
ArrayList<Vertex> list1 =new ArrayList<Vertex>();
Map<Integer, Object> map=new HashMap<>(8);
int stuNum = 8;//学期数
int max = 6;//最大学分
int j = 0;//临时下标
for(int i =1 ; i <= stuNum ; i++) {
if(j<=list.size()-2){
while(true){
int a = list.get(j).score;
if(a < max / 2 ) {
list1.add(list.get(j));
list1.add(list.get(j+1));
map.put(i,list1);
list1=new ArrayList<Vertex>();
j+=2;
break;
}else {
list1.add(list.get(j));
map.put(i,list1);
list1=new ArrayList<Vertex>();
j++;
break;
}
}
}else if(j == list.size()-1){
list1.add(list.get(j));
map.put(i,list1);
j++;
}else {
list1.add(new Vertex("无","无",0));
map.put(i,list1);
list1=new ArrayList<Vertex>();
}
}
return map;
}
}
6.总结
一开始没有连接数据库,就是用System.out.println不断的进行输出判定,因为效率问题采用了数据库存储的方法,使用时只要读取数据库的数据即可。提高平时运算的效率。虽然可以最后显示出来了,但初次写的代码肯定有优化的空间。只有不断的实验和诊断才能写成一个可以适用的好程序。总之,以后的路还很长,学习的东西还有很多。每次的课程设计都是对自己能力的提升,感谢老师同学的帮助与支持。