数据结构实验五教学计划编制课案.docx

上传人:b****6 文档编号:5821975 上传时间:2023-01-01 格式:DOCX 页数:20 大小:80.98KB
下载 相关 举报
数据结构实验五教学计划编制课案.docx_第1页
第1页 / 共20页
数据结构实验五教学计划编制课案.docx_第2页
第2页 / 共20页
数据结构实验五教学计划编制课案.docx_第3页
第3页 / 共20页
数据结构实验五教学计划编制课案.docx_第4页
第4页 / 共20页
数据结构实验五教学计划编制课案.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

数据结构实验五教学计划编制课案.docx

《数据结构实验五教学计划编制课案.docx》由会员分享,可在线阅读,更多相关《数据结构实验五教学计划编制课案.docx(20页珍藏版)》请在冰豆网上搜索。

数据结构实验五教学计划编制课案.docx

数据结构实验五教学计划编制课案

HUNANUNIVERSITY

实验五最终报告

 

题目教学计划编制问题

学生姓名

学生学号

专业班级

指导老师李晓鸿

完成日期2015年12月17日

一.需求分析

1.程序的功能

用户通过键盘输入课程总数、每门课的课程编号和直接先修的课程号等的参数。

用有向网表示教学计划,其中顶点表示某门课程,有向边表示课程之间的先修关系(如果A课程是B课程的先修课程,那么A到B之间有一条有向边从A指向B)。

最终输出一个不冲突的线性的课程教学流程。

2.输入形式

请输入课程总数:

//输入一个正整数n

请输入课程1的名称:

//输入任意字符串

请输入课程2的名称:

..............

请输入课程n的名称:

(课程1)否是有先修(1/0):

//输入1表示有,0表示没有

若输入1:

请输入先修课程的名称:

//输入存在的先修课程名称

...............

(课程n)否是有先修(1/0):

请输入先修课程的名称:

3.输出形式

输出成功:

课程表的排序为:

//输出没有冲突的课表排序

输出失败:

课程输入错误!

教学计划编制失败,请重新输入。

4.测试数据:

①.正常的输入

输入:

输入课程总数:

3

请输入课程1的名称:

小学数学

请输入课程2的名称:

初中数学

请输入课程3的名称:

大学数学

小学数学是否有先修(1/0):

0

初中数学是否有先修(1/0):

1

请输入先修课程的名称:

小学数学

高中数学是否有先修(1/0):

1

请输入先修课程的名称:

初中数学

输出:

课程表的排序为:

小学数学初中数学高中数学

②.正常的输入

输入:

输入课程总数:

4

请输入课程1的名称:

1

请输入课程2的名称:

2

请输入课程3的名称:

3

请输入课程4的名称:

4

1是否有先修(1/0):

0

请输入先修课程的名称:

4

2是否有先修(1/0):

1

请输入先修课程的名称:

3

3是否有先修(1/0):

1

请输入先修课程的名称:

4

4是否有先修(1/0):

0

输出:

课程表的排序为:

4132

③.有两个先修课程的情况

输入:

输入课程总数:

4

请输入课程1的名称:

A

请输入课程2的名称:

B

请输入课程3的名称:

C

请输入课程4的名称:

D

A是否有先修(1/0):

0

B是否有先修(1/0):

1

请输入先修课程的名称:

A

C是否有先修(1/0):

1

请输入先修课程的名称:

A

D是否有先修(1/0):

1

请输入先修课程的名称:

C

输出:

课程表的排序为:

ABCD

④.有三个先修课程的情况

输入:

输入课程总数:

4

请输入课程1的名称:

A

请输入课程2的名称:

B

请输入课程3的名称:

C

请输入课程4的名称:

D

A是否有先修(1/0):

1

请输入先修课程的名称:

D

B是否有先修(1/0):

1

请输入先修课程的名称:

D

C是否有先修(1/0):

1

请输入先修课程的名称:

D

D是否有先修(1/0):

0

输出:

课程表的排序为:

DABC

⑤.所有课程无先修

输入:

输入课程总数:

3

请输入课程1的名称:

1

请输入课程2的名称:

2

请输入课程3的名称:

3

A是否有先修(1/0):

0

B是否有先修(1/0):

0

C是否有先修(1/0):

0

输出:

课程表的排序为:

123

二、概要设计

1.抽象数据类型

题设要求使用一个有向图表示教学计划,顶点表示某门课程,有向边表示课程之间的先修关系,数据的对象是图中的每一个顶点和有向边。

由此为本问题确定一个图的数据关系。

本题目需要一个数据结构来储存遍历过的图的结点,该数据结构满足先进先出,所以用队列来实现。

2.ADT

ADTEdge{

数据对象:

N(边的名称)V(标记)F(先修课结点)

数据关系:

(N&&V&&F)∈R

(R1&&R2&&Rn)∈Graph

基本操作:

stringgetVal(intv)//返回边的名称

intgetMark(intv)//返回标记

voidsetVal(intv,stringval)//设边的名称

voidsetMark(intv,intMark)//设置标记

voidsetfirst(intv)//设置先修结点标记

}

ADTGraph{

数据对象:

V,R(分别代表某门课程的顶点组成的一个顶点集 V 和代表课程先修关系的有向弧边组成的一个弧集 R。

数据关系:

VR={|v,w∈V且P(v,w)}

表示从v到w的一条弧,并称v为弧头,w为弧尾。

基本操作:

intn();//返回图中的顶点数

intfirst(int);//返回该点的第一条邻边

intnext(int);//返回该店的下一条邻边

voidsetEdge(int,int,int);//为有向边设置权值

voidFind(stringsearch,int&v)

intn()

}

 

ADTqueue{

数据对象:

前指针front,后指针rear

数据关系:

R={|ai-1,ai∈car,i=1,2,3….n}

约定a1为队列头,an为队列尾。

基本操作:

queue();//队列结构初始化

~queue();//结构销毁操作

boolpush(constint&it);//数据入列

boolpop(int&it);//数据出列

intsize();//获取队列长度}

3.算法的基本思想

①.通过用户输入的顶点的个数(课程数)初始化一个表示有向图的相邻矩阵,初始化边的访问次数全部设置为零,通过输入边的信息和先修关系,设置先修关系的计数器,记录每条边先修关系的数量,完成对有项图的构建。

②.将先修关系为零的边放入队列,然后开始处理队列。

当从队列中删除一个顶点时,把它打印出来,同时将其所有相邻顶点的先修关系计数器减一。

当某个相邻顶点的计数器为0时,就将其放入队列。

如果还有顶点未被打印,而队列已经为空,则图中必然包含回路(既不可能不违反先决条件完成任务)。

4.程序的流程

(1)初始化模块:

输入课程总数,再输入相应数量的课程编号及每个课程的先修课程,用这些信息初始化一个有向图。

(2)拓扑排序模块:

对有向图进行拓扑排序。

(3)输出模块:

根据有向图是否为空输出。

为空时,输出拓扑排序结果;不为空时输出输入错误提示。

三、详细设计

1.物理数据类型

用户输入的课程个数不定,所以存储拓扑排序后的顶点的个数不定,对于图有两种存储方式,本题中用邻接矩阵来存储图的信息,对于边很少的图来说,虽然用邻接矩阵有些浪费空间,但是题目做起来相对方便。

由于用户输入的课程个数不定,使用链式栈。

使用string类型储存用户信息和边的信息。

2.算法的具体步骤

初始化一个有向图——先修信息的储存——拓扑排序与输出

①.初始化一个有向图:

包括初始化被访问标记和先修标记,动态创建二维数组和用于储存边信息的一维数组。

Graph(intnumVert)

{

inti,j;

numVertex=numVert;

numEdge=0;

mark=newPoint[numVert];//Initializemarkarray

for(i=0;i

{

mark[i].visit=-1;//包括初始化被访问标记和先修标记

mark[i].first=0;

}

matrix=(int**)newint*[numVertex];//Makematrix

for(i=0;i

matrix[i]=newint[numVertex];

for(i=0;i

for(intj=0;j

}

②.先修信息的存储:

由用户输入是否有先修课程后,用户每输入一个先修课程,就将这个课程对应的先修标记加1.

cout<

cin>>judge;

if(judge)

{

a.setfirst(i);

cout<<"请输入先修课程的名称:

";

cin>>Ch1;

a.Find(Ch1,v1);

a.setEdge(v1,i,10);

}

voidsetfirst(intv)

{

mark[v].first++;

}

③.拓扑排序与输出:

定义两个队列A和B,将先修关系为零的边放入队列A,然后开始处理队列。

当从队列A中删除一个顶点时,该顶点进入B队列,再把该顶点打印出来,同时将其所有相邻顶点的先修关系计数器减一。

当某个相邻顶点的计数器为0时,就将其放入队列。

如果还有顶点未被打印,而队列已经为空,则图中必然包含回路(既不可能不违反先决条件完成任务)。

输出:

重复将队列B中首元素输出并删除,直到队列为空,就是课程表的排序。

voidDFS(Graph*G,queue*Q,queue*L)

{

for(intv=0;v

if(mark[v].first==0)

{

Q->push(v);

setMark(v,1);

}

while(Q->size()!

=0)

{

inti=Q->front();//获取Q栈首元素

Q->pop();//弹出Q栈

L->push(i);//进L栈

for(intw=first(i);w

{

mark[w].first--;

if(mark[w].first==0)

{

Q->push(w);setMark(w,1);

}

}

}

for(inti=0;i

{

if(getMark(i)==-1)//为0时表示还未被删除,图不为空

{

cout<<"课程输入错误!

教学计划编制失败,请重新输入。

"<

exit(0);

}

}

}

3.算法的时空分析及改进设想

因为图的邻接矩阵是一个|V|×|V|矩阵,所以邻接矩阵的空间代价为Θ(|V|^2),对于有n个顶点的和E条弧的有向图而言,对此图的拓扑排序算法时间复杂度为Θ(V+E)

4.输入和输出的格式

输入:

1.输入课程数n

cout<<"请输入课程总数:

";

cin>>n;

if(n<=0)

{

cout<<"输入错误重新输入(大于零的整数)"<

cout<<"请输入课程总数:

";

cin>>n;

}

2.输入每门课的课程编号

for(inti=0;i

{

cout<<"请输入课程"<

";

cin>>Ch;

a.setVal(i,Ch);

}

3.获得先修的课程编号

for(inti=0;i

{

judge=0;

cout<

cin>>judge;

if(judge)

{

a.setfirst(i);

cout<<"请输入先修课程的名称:

";

cin>>Ch1;

a.Find(Ch1,v1);

a.setEdge(v1,i,10);

}

}

输出:

1.编制成功,把队列S中的顶点序列输出。

cout<<"课程表的排序为:

"<

a.DFS(&a,&Q,&L);

for(inti=0;i

{

intj=L.front();

cout<

L.pop();

}

2.编制失败,图中有回路,输出错误信息,结束程序。

if(G.getMark(i)==0)//为0时表示该顶点未经过拓扑排序

{

cout<<"课程输入错误!

教学计划编制失败,请重新输入。

"<

exit(0);

}

四.调试分析

DFS问题,书上思路很明确并且有很多源码,没有大的问题。

五.测试结果

1.正常的输入输出

②.正常的输入

3.有两个先修课程的情况

④.有三个先修课程的情况

⑤.所有课程无先修

附录

#include

#include

#include

#include

#include

usingnamespacestd;

classPoint

{

public:

stringLessonName;

intvisit;

intfirst;//1有先修,0无

};

classGraph

{//Implementadjacencymatrix

private:

intnumVertex,numEdge;//Storenumberofverticesedges

int**matrix;//Pointertoadjacencymatrix

Point*mark;//Pointertomarkarray

public:

Graph(intnumVert)

{//Makegraphw/numVertvertices

inti,j;

numVertex=numVert;

numEdge=0;

mark=newPoint[numVert];//Initializemarkarray

for(i=0;i

{

mark[i].visit=-1;

mark[i].first=0;

}

matrix=(int**)newint*[numVertex];//Makematrix

for(i=0;i

matrix[i]=newint[numVertex];

for(i=0;i

for(intj=0;j

}

~Graph()

{

delete[]mark;

for(inti=0;i

delete[]matrix[i];

delete[]matrix;

}

intn()

{

returnnumVertex;

}

inte()

{

returnnumEdge;

}

intfirst(intv)

{//Returnv'sfirstneighbor

inti;

for(i=0;i

if(matrix[v][i]!

=0&&mark[i].visit==-1)returni;

returni;//Returnnifnone

}

intnext(intv1,intv2)

{

//Getv1'sneighborafterv2

inti;

for(i=v2+1;i

if(matrix[v1][i]!

=0&&mark[i].visit==-1)

{

//cout<<"此时next的i值是:

"<

returni;

}

returni;

}

//Setedge(v1,v2)towgt

voidsetEdge(intv1,intv2,intwgt)

{

numEdge++;//ERROR

matrix[v1][v2]=wgt;

}

voiddelEdge(intv1,intv2)

{//Deleteedge(v1,v2)

if(matrix[v1][v2]!

=0)

numEdge--;

matrix[v1][v2]=0;

}

intweight(intv1,intv2)

{

returnmatrix[v1][v2];

}

stringgetVal(intv)

{

returnmark[v].LessonName;

}

intgetMark(intv)

{

returnmark[v].visit;

}

voidsetVal(intv,stringval)

{

mark[v].LessonName=val;

}

voidsetMark(intv,intMark)

{

mark[v].visit=Mark;

}

voidsetfirst(intv)

{

mark[v].first++;

}

voidFind(stringsearch,int&v)

{

for(inti=0;i

{

if(mark[i].LessonName==search)

{

v=i;

return;

}

}

cout<<"路径错误"<

return;

}

voidDFS(Graph*G,queue*Q,queue*L)

{

for(intv=0;v

if(mark[v].first==0)

{

Q->push(v);

setMark(v,1);

}

while(Q->size()!

=0)

{

inti=Q->front();//获取Q栈首元素

Q->pop();//弹出Q栈

L->push(i);//进L栈

for(intw=first(i);w

{

mark[w].first--;

if(mark[w].first==0)

{

Q->push(w);setMark(w,1);

}

}

}

for(inti=0;i

{

if(getMark(i)==-1)//为0时表示还未被删除,图不为空

{

cout<<"课程输入错误!

教学计划编制失败,请重新输入。

"<

exit(0);

}

}

}

};

intmain()

{

intn;

intv1;

intv2;

intjudge;

stringCh;

stringCh1;

stringCh2;

queueQ;

queueL;

intD[100];

intcount=0;

cout<<"请输入课程总数:

";

cin>>n;

if(n<=0)

{

cout<<"输入错误重新输入(大于零的整数)"<

cout<<"请输入课程总数:

";

cin>>n;

}

Grapha(n);

for(inti=0;i

{

cout<<"请输入课程"<

";

cin>>Ch;

a.setVal(i,Ch);

}

for(inti=0;i

{

judge=0;

cout<

cin>>judge;

if(judge)

{

a.setfirst(i);

cout<<"请输入先修课程的名称:

";

cin>>Ch1;

a.Find(Ch1,v1);

a.setEdge(v1,i,10);

}

}

cout<<"课程表的排序为:

"<

a.DFS(&a,&Q,&L);

for(inti=0;i

{

intj=L.front();

cout<

L.pop();

}

system("pause");

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 生产经营管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1