关键路径算法课程设计Word文件下载.docx
《关键路径算法课程设计Word文件下载.docx》由会员分享,可在线阅读,更多相关《关键路径算法课程设计Word文件下载.docx(11页珍藏版)》请在冰豆网上搜索。
1.2题目理解与功能分析
该题实质要求用数据结构中的图形知识编写一个求无循环有向帯权图中从起点到终点所有路径,经分析、比较求出长度最大路径,从而求出关键路径。
通常我们用有向图表示一个工程。
在这种有向图中,用顶点表示活动,用有向边<
Vi,Vj>
表示活动Vi必须先于活动Vj进行。
如果在这种图中用有向边表示一个工程中的各项活动(ACTIVITY),用有向边上的权值表示活动的持续时间(DURATION),用顶点表示事件(EVENT),则这种的有向图叫做用边表示活动的网络,简称AOE网络。
在AOE网络中,从源点到各个顶点,可能不止一条。
这些路径的长度也可能不同。
不同路径所需的时间虽然不同,但只有各条路径上所有活动都完成了,这个工程才算完成。
因此,完成整个工程所需的时间取决于从源点到汇点的最长路径长度,即在这条路径上所有活动的持续时间之和。
这条路径长度就叫做关键路径(criticalpath)。
程序所要达到的功能:
输入并建立AOE网;
输出关键活动并求出这个工程的关键路径;
求出完成这个关键路径的最少时间并输出,该程序结束。
第二章概要设计
2.1设计思路
基本设计思路:
(1)以某一个求无循环有向帯权图蓝本。
(2)观察并记录这个图中每个弧的起始点及权值。
(3)用记录的结果建立AOE网,即边表示活动的网络,并用图的形式表示。
(4)用领接表来存储图这些信息。
(5)用CreateGraph()函数建立AOE图。
(6)用SearchMapPath()函数求出最大路径,并打印出关键路径。
(7)编写代码并测试。
2.2系统模块图
图2-1系统模块图
第三章详细设计
3.1图存储结构的建立
1.先建立邻接表的存储单元,为建立邻接表做准备。
为图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi的边(对于有向图是以vi为尾的弧)。
每个结点由3个域组成,其中邻接域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextedge)指示下一条边或弧的结点,权值域(W)存储边或弧的权值大小。
在表头结点除了设有链域(firstedge)指向链表中第一个结点之外,还设有存储顶点v或其他有关的数据域(data)和存储顶点入度的域(id)(代码如下)。
typedefstructnode{
intadjvex;
intw;
structnode*nextedge;
}edgenode;
typedefstruct{
chardata;
intid;
edgenode*firstedge;
}vexnode;
2.然后构造有向图。
第一,输入顶点信息存储在顶点表中,并初始化该顶点的便表。
第二,首先输入边所依附的两个顶点的序号i和j然后生成新的邻接点序号为j的边表结点,最后将该结点插入到第i个表头部。
(代码如下)
for(intk=0;
k<
arcnumber;
k++){
scanf("
%d,%d,%d"
&
begin,&
end,&
duttem);
p=(edgenode*)malloc(sizeof(edgenode));
p->
adjvex=end-1;
w=duttem;
Graph[end-1].id++;
nextedge=Graph[begin-1].firstedge;
Graph[begin-1].firstedge=p;
3.2求取关键路径
利用AOE网进行工程管理时,需解决的两个主要问题:
其一,计算完成整个工程的最短工期;
其二,确定关键路径,以找出哪些活动时影响工程进度的关键。
因此须计算以下几点:
(1)事件的最早发生时间ve[k];
(2)事件最迟发生时间vl[k];
(3)活动最早开始时间ee[i];
(4)活动的最迟开始时间el[i];
计算其过程必须分别在拓扑有序和逆拓扑有序的前提下进行。
也就说,ve[k]必须在事件vk所有前驱的最早发生的时间求得之后才能确定。
因此,可以在拓扑排序的基础上计算ve[k]和vl[k]。
由此得到求解关键路径的方法:
首先输入e条有向边<
i,j>
,建立AOE网的邻接表存储结构;
然后从始点出发,令事件的最早发生时间为0,按拓扑有序求其余各顶点时间的最早发生时间ve[k];
while(p){
k=p->
adjvex;
Graph[k].id--;
if(ve[j]+p->
w>
ve[k])
ve[k]=ve[j]+p->
w;
}
接着从终点出发,令事件最迟发生时间等于其最早发生时间,按你你逆拓扑排序求其余各顶点事件最迟发生时间vl[k];
最后根据各顶点事件的ve和vl值,求所有活动最早开始时间ee和最迟开始时间el。
如果某活动满足条件ee=el,则为关键活动。
if(el[i]==ee[i]){
printf("
此弧为关键活动"
);
}
同时,为计算各顶点事件的ve值是在拓扑排序的过程中进行的,因此需一个队列来记录拓扑排序,如果顶点的入度为0,则该顶点从队尾进入队列,拓扑排序时,从队头出队列。
if(Graph[k].id==0)
topology_queue[++rear]=k;
p=p->
nextedge;
3.3主程序建立
该部分主要是对所建立的函数的调用。
包括:
建立图的函数CreateGraph();
计算关键路径的函数SearchMapPath();
最后程序结束。
这样安排可以增强程序的可读性,是程序便于理解,也便于日后的对程序的维护和修改等操作。
第四章实验结果
按照要求输入一组关于无循环有向帯权图所有信息。
依次执行程序每一步,最后结束该程序。
程序运行如下图:
图4-1运行结果
参考文献
[1]严蔚敏编.数据结构(C语言版).北京:
清华大学出版社,1997.2
[2]谭浩强著.C语言程序设计(第二版).北京:
清华大出版社,2001.3
[3]夏克俭编著.数据结构.北京:
国防工业出版社,2000.7
[4]彭勃.数据结构.北京:
电子工业出版社,2007.6
[5]宜晨编著.VisualC++5.0实用培训教程.北京:
电子工业出版社,1998.5
[6]崔武子.C语言程序设计实践教程.北京:
清华大出版社,2006.1
[7]庞振平.计算机程序设计基础.广州:
华南理工出版社,2002.9
附录(程序清单)
#include<
stdio.h>
stdlib.h>
intadjvex;
structnode*nextedge;
chardata;
intid;
edgenode*firstedge;
voidCreateGraph(vexnode*Graph,intvexnumber,intarcnumber){
intbegin,end,duttem;
charch;
edgenode*p;
for(inti=0;
i<
vexnumber;
i++){
Graph[i].id=0;
Graph[i].firstedge=NULL;
printf("
请输入这个图中的各个顶点的值:
\n"
for(i=0;
i++){
%s"
ch);
Graph[i].data=ch;
}
请输入图中弧的起始点及权值:
其格式为<
起点,终点,权值>
}
}
intSearchMapPath(vexnode*Graph,intvexnumber,intarcnumber){
inttotaltime=0;
intm=0;
inti,j,k,t;
charsv[100];
intfront,rear;
int*topology_queue,*vl,*ve,*el,*ee;
front=rear=-1;
t=0;
topology_queue=(int*)malloc(vexnumber*sizeof(int));
vl=(int*)malloc(vexnumber*sizeof(int));
ve=(int*)malloc(vexnumber*sizeof(int));
el=(int*)malloc(arcnumber*sizeof(int));
ee=(int*)malloc(arcnumber*sizeof(int));
i++)ve[i]=0;
if(Graph[i].id==0)
topology_queue[++rear]=i;
m++;
}
while(front!
=rear){
front++;
j=topology_queue[front];
m++;
p=Graph[j].firstedge;
k=p->
Graph[k].id--;
if(ve[j]+p->
if(Graph[k].id==0)topology_queue[++rear]=k;
if(m<
vexnumber)
{
\n本程序所建立的图有回路不可计算出关键路径\n"
将退出本程序\n"
return0;
totaltime=ve[vexnumber-1];
i++)
vl[i]=totaltime;
for(i=vexnumber-2;
i>
=0;
i--){
j=topology_queue[i];
p=Graph[j].firstedge;
if((vl[k]-p->
w)<
vl[j])
vl[j]=vl[k]-p->
w;
nextedge;
}
|起点|终点|最早开始时间|最迟开始时间|差值|是否为关键路径\n"
i=0;
for(j=0;
j<
j++)
{
ee[++i]=ve[j];
el[i]=vl[k]-p->
|%4c|%4c|%12d|%12d|%4d|"
Graph[j].data,Graph[k].data,ee[i],el[i],el[i]-ee[i]);
if(el[i]==ee[i]){
sv[t]=Graph[j].data;
t++;
关键路径节点为:
"
sv[t]=Graph[vexnumber-1].data;
=t;
%c"
sv[i]);
if(sv[i]!
=Graph[vexnumber-1].data)
printf("
--->
关键路径长度为:
%d个单位时间\n"
totaltime);
return1;
}
voidmain(){
intvexnumber,arcnumber,totaltime=0;
请输入这个图中的节点数:
%d"
vexnumber);
请输入这个图中的弧数:
arcnumber);
vexnode*Graph=(vexnode*)malloc(vexnumber*sizeof(vexnode));
CreateGraph(Graph,vexnumber,arcnumber);
SearchMapPath(Graph,vexnumber,arcnumber);
课程设计总结:
从这次给我的课程设计任务中我深刻地体会到了。
任何事情并不是想我们想的那样简单和容易。
只有扎扎时时的学习知识才能解决实际生活中的实际问题。
从这次课设中也让我明白以后要多了解相关知识,更多的做一些实践动手活动,将知识运用到实际问题中。
同时,增加自己的动手能力,这样才能便于我们更好的解决问题。
为今后打下好的基础。
当我编完程序后,我感到很欣喜,这毕竟是我的第一次课程设计任务。
能完成让我感到什么叫做编程的快乐,什么叫做乐趣。
督促我更加努力的学习我的专业课:
计算机科学与技术。
指导教师评语:
指导教师(签字):
年月日
课程设计成绩