实验五 教学计划的编制问题.docx
《实验五 教学计划的编制问题.docx》由会员分享,可在线阅读,更多相关《实验五 教学计划的编制问题.docx(15页珍藏版)》请在冰豆网上搜索。
![实验五 教学计划的编制问题.docx](https://file1.bdocx.com/fileroot1/2023-7/16/4799c435-d5c7-40cb-9dc3-9e7a1304dfbc/4799c435-d5c7-40cb-9dc3-9e7a1304dfbc1.gif)
实验五教学计划的编制问题
HUNANUNIVERSITY
课程实验报告
题目:
教学计划的编制问题
学生姓名
学生学号201208010
专业班级计算机科学与技术班
完成日期
一、需求分析
(1)输入的形式和输入值的范围:
输入参数:
课程总数,每门课的课程号(固定占3位的字母数字串)和直接先修课的课程号。
(2)输出的形式:
若根据输入条件问题无解,则报告适当的信息;否则将教学计划输出到用户指定的文件中。
(3)程序所能达到的功能:
按照用户的输入,给出每学期应学的课程。
(4)测试数据:
输入:
7(结点数)8(边的数量)
结点1:
mat
结点2:
che
结点3:
eng
结点4:
phy
结点5:
bio
结点6:
geo
结点7:
com
边1:
matche
边2:
mateng
边3:
cheeng
边4:
chephy
边5:
phygeo
边6:
phybio
边7:
geocom
边8:
enggeo
输出:
matchephybioenggeocom
二、概要设计
抽象数据类型
为实现上述功能,我们建立一个结点类,线性表类和图类。
结点的ADT如下:
数据类型:
字符串
由于定义的结点是属于图的元素,故没有基本操作,里面所有的元素都用public存储。
线性表的ADT如下:
数据对象:
D={ai|aiЄNode}
数据关系:
R1={|ai,ai+1ЄD}
基本操作:
voidinsert(intv,stringch)//插入元素
图的ADT如下:
数据对象:
具有相同数据的结点类组成的顶点集
数据关系:
R1={|w,vЄNode,w,v表示w,v之间存在直接先修关系}
基本操作:
voidpushVertex()//读入点
voidpushEdge()//读入边
voidtopsort()//拓扑排序
算法的基本思想
先建立一个结点类,类中数据包括字符串、当前位置以及其指向的元素位置以及入度出度。
为了方便实现这个算法,图用线性表来存储,线性表中的元素为结点类。
将图中结点和边的关系输入这个图中,然后进行拓扑排序,若拓扑排序成功则输出正确的顺序,若不成功即有回路则输出提示语句。
程序流程
程序由三个模块组成:
(1)输入模块:
读入图的信息(顶点和边,用线性表进行存储)。
(2)处理模块:
topsort算法。
(3)输出模块:
将结果输出。
各程序模块之间的层次关系
主函数会先调用输入模块确定图的结点和边,再循环调用Topsort算法,最后将结果提示给用户。
三、详细设计
实现概要设计中的数据类型
用整型存储用户的输入,并将相应数据存入Node类。
classNode{//结点类
public:
stringnode;
intposition;//位置
Node*next;
boolvisit;//是否被访问
Node(){visit=false;next=NULL;position=0;node='';}
};
classLine{//线性表类
public:
intnum;
Node*head;
Node*rear;
Node*fence;
Line(){num=0;head=fence=rear=newNode();}
voidinsert(intv,stringch){//插入元素
Node*current=newNode();
current->node=ch;
current->position=v;
fence->next=current;
fence=current;
num++;
}
};
classGraph{//图类
private:
intnumVertex;
intnumEdge;
Line*line;
public:
Graph(intv,inte){numVertex=v;numEdge=e;line=newLine[v];}
voidpushVertex(){//读入点
stringch;
for(inti=0;icout<<"请输入顶点"<
";
cin>>ch;
line[i].head->node=ch;
line[i].head->position=i;
}
}
voidpushEdge(){//读入边
stringch1,ch2;
intpos1,pos2;
for(inti=0;i{
cout<<"请输入边"<
";
cin>>ch1>>ch2;
for(intj=0;jif(line[j].head->node==ch1)
pos1=j;//找到该字母对应的位置
if(line[j].head->node==ch2){
pos2=line[j].head->position;
break;
}
}
line[pos1].insert(pos2,ch2);
}
}
Topsort算法:
先计算每个点的入度,保存在数组中。
找到第一个入度为0的点,将该点所连的各点的入度减一。
再在这些点中找入度为0的点。
如果找到,重复上述操作。
如果找不到,则跳出while循环,再搜索其他的点,看入度是否为0。
再重复上述操作,如果所有的入度为0的点都被寻找到,但个数少于输入顶点的个数,说明该图存在环。
voidtopsort(){//拓扑排序
inti;
int*d=newint[numVertex];
for(i=0;id[i]=0;//数组初始化
for(i=0;iNode*p=line[i].head;
while(p->next!
=NULL){
d[p->next->position]++;//计算每个点的入度
p=p->next;
}
}
inttop=-1,m=0,j,k;
for(i=0;iif(d[i]==0){
d[i]=top;//找到第一个入度为0的点
top=i;
}
while(top!
=-1){
j=top;
top=d[top];
cout<node<<"";
m++;
Node*p=line[j].head;
while(p->next!
=NULL){
k=p->next->position;
d[k]--;//当起点被删除,时后面的点的入度-1
if(d[k]==0){
d[k]=top;
top=k;
}
p=p->next;
}
}
}
cout<if(mcout<<"网络存在回路"<delete[]d;
}
};
intmain(){
intn,m;
cout<<"请输入节点的个数和边的个数"<cin>>n>>m;
GraphG(n,m);
G.pushVertex();
G.pushEdge();
G.topsort();
system("pause");
return0;
}
算法的时空分析
时间复杂度:
O(n),空间复杂度:
O(n);
函数的调用关系图
开始
↓
输入图的结点数和边数
↓
输入图中各个课程名称
↓
输入边关系
↓
拓扑排序
↓
结束
输入和输出的格式
输入:
7(结点数)8(边的数量)
结点1:
mat
结点2:
che
结点3:
eng
结点4:
phy
结点5:
bio
结点6:
geo
结点7:
com
边1:
matche
边2:
mateng
边3:
cheeng
边4:
chephy
边5:
phygeo
边6:
phybio
边7:
geocom
边8:
enggeo
输出:
matchephybioenggeocom
四、测试结果
五、用户使用说明(可选)
1、本程序的运行环境为DOS操作系统,执行文件为教学计划编制.exe
2、运行程序时:
(1)显示提示“请输入结点数和边数”,此时输入结点数和边数。
(2)数据输入完毕后,拓扑排序若成功则输出排序结果,若不成功则输出提示语句。
六、实验心得
这次实验让我更加了解图的定义,对课堂内容更加了解。
七、附录
#include
#include
usingnamespacestd;
classNode{//结点类
public:
stringnode;
intposition;//位置
Node*next;
boolvisit;//是否被访问
Node(){visit=false;next=NULL;position=0;node='';}
};
classLine{//线性表类
public:
intnum;
Node*head;
Node*rear;
Node*fence;
Line(){num=0;head=fence=rear=newNode();}
voidinsert(intv,stringch){//插入元素
Node*current=newNode();
current->node=ch;
current->position=v;
fence->next=current;
fence=current;
num++;
}
};
classGraph{//图类
private:
intnumVertex;
intnumEdge;
Line*line;
public:
Graph(intv,inte){numVertex=v;numEdge=e;line=newLine[v];}
voidpushVertex(){//读入点
stringch;
for(inti=0;icout<<"请输入顶点"<
";
cin>>ch;
line[i].head->node=ch;
line[i].head->position=i;
}
}
voidpushEdge(){//读入边
stringch1,ch2;
intpos1,pos2;
for(inti=0;i{
cout<<"请输入边"<
";
cin>>ch1>>ch2;
for(intj=0;jif(line[j].head->node==ch1)
pos1=j;//找到该字母对应的位置
if(line[j].head->node==ch2){
pos2=line[j].head->position;
break;
}
}
line[pos1].insert(pos2,ch2);
}
}
voidtopsort(){//拓扑排序
inti;
int*d=newint[numVertex];
for(i=0;id[i]=0;//数组初始化
for(i=0;iNode*p=line[i].head;
while(p->next!
=NULL){
d[p->next->position]++;//计算每个点的入度
p=p->next;
}
}
inttop=-1,m=0,j,k;
for(i=0;iif(d[i]==0){
d[i]=top;//找到第一个入度为0的点
top=i;
}
while(top!
=-1){
j=top;
top=d[top];
cout<node<<"";
m++;
Node*p=line[j].head;
while(p->next!
=NULL){
k=p->next->position;
d[k]--;//当起点被删除,时后面的点的入度-1
if(d[k]==0){
d[k]=top;
top=k;
}
p=p->next;
}
}
}
cout<if(mcout<<"网络存在回路输入错误"<delete[]d;
}
};
intmain(){
intn,m;
cout<<"请输入节点的个数和边的个数"<cin>>n>>m;
GraphG(n,m);
G.pushVertex();
G.pushEdge();
G.topsort();
system("pause");
return0;
}