设计求解AOE网关键路径程序(详细设计,附完整实现代码)

2023-12-30 01:50

本文主要是介绍设计求解AOE网关键路径程序(详细设计,附完整实现代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、课程设计内容

二、课程设计实现功能

三、具体实现功能过程以及可能遇到的问题

四、实现程序功能模块图

五、具体实现代码(完整代码C语言)

六、演示如何操作(注意输入信息,这里以上面AOE网为准输入)

6.1先输入AOE网的顶点个数和边数

6.2输入顶点元素(复制粘贴一下即可)

6.3输入边的信息(复制粘贴即可)

6.5运行结果页面展示

6.5.1AOE输入信息图:

6.5.2图的邻接表示图: 

6.5.3关键路径图和最短总工程时间:

七、总结与心得体会


坚持阅读,才能发现美的存在!

更多精彩等你哦!

一起来场跨时空的交流。

一、课程设计内容

设计内容:某新房精装修项目工作内容主要包括:(A)施工作业场所检验交接;(B)窗橱,门框防护;(C)防水作业;(D)土建改造;(E)防水检验接收;(F)水电检验接收;(G)原始地面防护;(H)铺贴瓷砖作业;(I)厅房吊顶作业;(J)天花吊顶作业;(K)顶棚一次面油;(L)墙面一次面油;(M)橱柜安装;(N)顶棚二次面油;(O)厨卫家电安装;(P)衣橱,门框进场作业;(Q)墙纸或墙面二次面油作业;(R)空调安装;(S)门扇安装;(T)木地板作业;(U)验收及整改;(V)施工完成并交付(将相应说明书的保留及移交物业)。根据以上各项工作内容具体工作时间如下表1所示。请构建本项目的AOE网,求出其关键路径及最短总工期。具体装修项目工期估计如下表1所以:

表1:某装修项目工期估计表

工作名称

工作内容

估计工期(单位:天)

A

施工作业场所检验交接

3

B

窗橱,门框防护

3

C

防水作业

10

D

土建改造

20

E

防水检验接收

3

F

水电检验接收

3

G

原始地面防护

2

H

铺贴瓷砖作业

6

I

厅房吊顶作业

10

J

天花吊顶作业

9

K

顶棚一次面油

14

L

墙面一次面油

10

M

橱柜安装

3

N

顶棚二次面油

10

O

厨卫家电安装

5

P

衣橱,门框进场作业

4

Q

墙纸或墙面二次面油作业

10

R

空调安装

3

S

门扇安装

3

T

木地板作业

10

U

验收及整改

20

V

施工完成并交接交付

17

二、课程设计实现功能

  1. 确定各项工作的先后关系,绘制AOE网络图;
  2. 计算AOE 网络图中的各活动时间;
  3. 确定关键路径;
  4. 计算最短总工期。

三、具体实现功能过程以及可能遇到的问题

1. 构建AOE网:根据用户输入的顶点个数和边数,使用邻接矩阵或邻接表的方式来表示图的结构。为每个顶点分配一个唯一的标识符,并将边的起始顶点和结束顶点添加到图中。可以使用二维数组表示邻接矩阵,或者使用链表表示邻接表。

2. 计算最早开始时间和最早完成时间:使用拓扑排序的方式来确定活动的顺序。从起始顶点开始,按照拓扑排序的顺序依次计算每个活动的最早开始时间和最早完成时间。对于每个活动,需要考虑其前驱活动的最早完成时间。可以使用深度优先搜索或广度优先搜索来进行拓扑排序。

3. 计算最晚开始时间和最晚完成时间:可以使用逆拓扑排序的方式来确定活动的顺序。从终点顶点开始,按照逆拓扑排序的顺序依次计算每个活动的最晚开始时间和最晚完成时间。对于每个活动,需要考虑其后继活动的最晚开始时间。可以使用深度优先搜索或广度优先搜索来进行逆拓扑排序。

4. 输出关键路径和最短总工期:通过比较每个活动的最早完成时间和最晚完成时间,可以确定关键路径上的活动。关键路径上的活动即为最早开始时间和最晚开始时间相等的活动。最短总工期可以通过终点顶点的最早完成时间来确定。

5. 错误处理:需要处理输入错误的情况,例如输入的顶点个数或边数为负数,活动的持续时间为负数等。可以使用条件判断语句来检查输入的有效性,并在出现错误时给出适当的提示信息。

6. 内存管理:在程序结束后,需要释放动态分配的内存,以防止内存泄漏。可以使用`malloc()`函数来分配内存,使用`free()`函数来释放内存。

四、实现程序功能模块图

4.1AOE网络图4.2程序流程图

五、具体实现代码(完整代码C语言)

#include <stdio.h>
#include <stdlib.h>
#define VertexType int //顶点的数据类型(char) 
#define VertexMax 40 //最大顶点个数 
typedef struct ArcNode//边表 
{int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置 int weight;//权值 struct ArcNode* next;
}ArcNode;typedef struct VNode //顶单个点 
{VertexType vertex;struct ArcNode* firstarc;
}VNode;typedef struct //顶点表 
{VNode AdjList[VertexMax];//由顶点构成的结构体数组 int vexnum, arcnum; //顶点数和边数 
}ALGraph;int LocateVex(ALGraph* G, VertexType v)
{int i;for (i = 0; i < G->vexnum; i++){if (v == G->AdjList[i].vertex){return i;}}printf("No Such Vertex!\n");return -1;
}//有向图 
void CreateDN(ALGraph* G)
{int i, j;//1.输入顶点数和边数 printf("输入顶点个数和边数:\n");printf("顶点数 n=");scanf("%d", &G->vexnum);printf("边  数 e=");scanf("%d", &G->arcnum);printf("\n");printf("\n");//2.顶点表数据域填值初始化顶点表指针域 printf("输入顶点元素(用空格隔开):");for (i = 0; i < G->vexnum; i++){/*printf("输入第%d个顶点信息:", i + 1);*/scanf(" %d", &G->AdjList[i].vertex);//printf("222%d", G->AdjList[i].vertex);G->AdjList[i].firstarc = NULL;}printf("\n");//3.输入边信息构造邻接表 int n, m;VertexType v1, v2;int weight;ArcNode* p1, * p2;printf("请输入边的信息:\n\n");for (i = 0; i < G->arcnum; i++){   //输入边信息,并确定v1和v2在G中的位置,即顶点在AdjList[]数组中的位置(下标)  printf("输入第%d条边信息:", i + 1);scanf(" %d%d,%d", &v1, &v2, &weight);n = LocateVex(G, v1);m = LocateVex(G, v2);if (n == -1 || m == -1){printf("NO This Vertex!\n");return;}p1 = (ArcNode*)malloc(sizeof(ArcNode));p1->adjvex = m;//填上坐标 p1->weight = weight;//填上权值 p1->next = G->AdjList[n].firstarc;//改链(头插法)  G->AdjList[n].firstarc = p1;}//for  
}void print(ALGraph G)
{int i;ArcNode* p;printf("\n-------------------------------");printf("\n图的邻接表表示:\n");for (i = 0; i < G.vexnum; i++){printf("\n   AdjList[%d]%4d", i, G.AdjList[i].vertex);p = G.AdjList[i].firstarc;while (p != NULL){printf("-->%d(%d)", p->adjvex+1, p->weight);p = p->next;}}printf("\n");printf("\n-------------------------------\n");
}int TopologicalSort(ALGraph* G, int* topo)
{int i;int top = -1;//栈顶指针 int Gettop;//用于存储/获取栈的栈顶元素 int count = 0;//用于统计拓扑排序生成的结点数(若生成结点数 < 图的结点数,则代表图中有环,拓扑排序不成功) int stack[VertexMax] = { 0 };//栈 int indegree[VertexMax] = { 0 };//入度数组 struct ArcNode* p;//临时变量 //1.计算顶点入度,并存入indegree数组中for (i = 0; i < G->vexnum; i++){if (G->AdjList[i].firstarc != NULL){p = G->AdjList[i].firstarc;while (p != NULL){indegree[p->adjvex]++;p = p->next;}}}//2.初始化部分:将初始入度为0的顶点入栈for (i = 0; i < G->vexnum; i++){if (indegree[i] == 0){stack[++top] = i;//先将指针加一在进行存储 }}//3.拓扑排序int m = 0;while (top != -1)//栈不为空 {Gettop = stack[top--];//获取栈顶元素,并且栈顶指针减一 topo[m++] = Gettop;//printf(" %c(%d)",G->AdjList[Gettop].vertex,topo[m-1]);//输出栈顶元素 count++;p = G->AdjList[Gettop].firstarc;while (p != NULL){indegree[p->adjvex]--;if (indegree[p->adjvex] == 0){stack[++top] = p->adjvex;}p = p->next;}}//4.判断拓扑排序是否成功(生成结点数 < 图的结点数,则代表图中有环,拓扑排序不成功) if (count < G->vexnum){printf("TopologicalSort Failed!\n");return 0; //拓扑排序失败 }elsereturn 1; //拓扑排序成功   
}void CriticalPath(ALGraph* G)
{int i;int j, k;// <Vj,Vk>int e, l;//活动最早开始时间/活动最晚开始时间  int topo[VertexMax];//拓扑数组,用于存储拓扑排序结果(存储内容是每个结点的坐标) int ve[VertexMax]; //事件vi的最早发生时间 int vl[VertexMax]; //事件vi的最晚发生时间 struct ArcNode* p;//1.调用拓扑排序,检测图是否存在环 if (!TopologicalSort(G, topo))//若拓扑排序成功,topo数组也将处理完毕 {return;}//2.正拓扑排序,求出事件最早发生时间 for (i = 0; i < G->vexnum; i++)ve[i] = 0;for (i = 0; i < G->vexnum; i++){j = topo[i];//j为起始点,k为终点 p = G->AdjList[j].firstarc;//用指针p去依次寻找j的每一个邻接点 while (p){k = p->adjvex;if (ve[k] < ve[j] + p->weight)//根据j的邻接点k,不断更新ve[]的值(选出最大值,原理类似于选择排序) {ve[k] = ve[j] + p->weight;}p = p->next;}}//3.逆拓扑排序,求出事件最迟发生时间 for (i = 0; i < G->vexnum; i++)vl[i] = ve[G->vexnum - 1];for (i = G->vexnum - 1; i >= 0; i--){j = topo[i];p = G->AdjList[j].firstarc;//让p去依次查找邻接点 while (p){k = p->adjvex;if (vl[j] > vl[k] - p->weight)//根据j的邻接点k,不断更新vl[]的值(选出最小值,原理类似于选择排序){vl[j] = vl[k] - p->weight;}p = p->next;}}//输出ve[i] printf("\tve[i]:");for (i = 0; i < G->vexnum; i++){printf("\t%d", ve[i]);}printf("\n");//输出vl[i]printf("\tvl[i]:");for (i = 0; i < G->vexnum; i++){printf("\t%d", vl[i]);}printf("\n\n");//4.计算e和l,通过判断e是否等于l确定该活动是否是关键活动,从而确定关键路径for (i = 0; i < G->vexnum; i++){p = G->AdjList[i].firstarc;//让p去依次查找邻接点 while (p){j = p->adjvex;e = ve[i];//计算活动最早开始时间 e l = vl[j] - p->weight;//计算活动最晚开始时间 l if (e == l)//如果e=l,说明该活动是关键活动 {printf("\t%d->%d(%d)\n", G->AdjList[i].vertex, G->AdjList[j].vertex, p->weight);}p = p->next;}}printf("最短总工期:%d\n", ve[16]);}int main()
{ALGraph G;//声明顶点表 顶点数和边数 CreateDN(&G);//根据输入顶点数和边,生成有向图 print(G); //打印有向图邻接表 printf("关键路径:\n\n");CriticalPath(&G);  //输出关键路径 正向拓扑排序,逆向拓扑排序,确定关键路径,输出关键路径 system("pause"); return 0;
}

六、演示如何操作(注意输入信息,这里以上面AOE网为准输入)

6.1先输入AOE网的顶点个数和边数

n= 17  

e = 22

6.2输入顶点元素(复制粘贴即可)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

6.3输入边的信息(复制粘贴即可)

1 2,3

2 3,3

3 4,10

3 5,20

4 6,3

5 6,3

6 7,6

6 8,10

6 11,2

7 11,9

8 9,14

8 10,10

9 11,10

10 11,10

11 12,3

11 13,3

11 14,4

12 15,5

13 15,3

14 15,10

15 16,20

16 17,17

 6.5运行结果页面展示
6.5.1AOE输入信息图:

6.5.2图的邻接表示图: 

 

 6.5.3关键路径图和最短总工程时间:

七、总结与心得体会

     在进行AOE拓扑排序程序设计开发过程中,我深刻体会到了以下几点:1. 计划和组织能力的重要性:在开始课程设计之前,我充分意识到了计划和组织的重要性。我制定了详细的计划和时间表,明确了每个阶段的任务和时间节点。我将整个课程设计分解为多个小任务,并合理安排了每个任务的时间和资源。这样,我能够更好地掌握整个项目的进度,及时调整和安排,确保项目的顺利进行。2. 需求分析的重要性:在进行课程设计之前,我进行了充分的需求分析。我与用户和相关人员进行了深入的沟通,了解了他们的需求和期望。我通过用户故事、用户画像等方式,对用户需求进行了详细的描述和分析。这样,我能够更好地理解用户的需求,确定关键功能和优先级,为后续的设计和开发提供了明确的方向。3. 设计思维的应用:在课程设计的过程中,我运用了设计思维的方法和工具。我通过用户故事、用户画像、原型设计等方式,深入理解用户需求,提出创新的解决方案。我将用户体验放在首位,注重用户的感受和需求,设计出更符合用户期望的解决方案。4. 团队合作的重要性:在进行课程设计的过程中,我与团队成员密切合作。我们共同讨论问题,提出解决方案,分工合作,共同努力实现项目的目标。我们通过有效的沟通和协作,解决了许多困难和问题。团队合作的力量是巨大的,它能够激发出团队成员的创造力和潜力,取得更好的成果。5. 测试和调试的重要性:在课程设计完成后,我进行了充分的测试和调试。我对程序进行了功能测试,确保程序的各个功能正常运行。我进行了性能测试,检查程序的性能是否满足需求。我进行了安全测试,确保程序的安全性和稳定性。通过测试和调试,我发现了一些问题,并及时进行了修复和优化,确保程序的正确性和可靠性。

     总之,通过这次课程设计,我不仅学到了专业知识和技能,还培养了自己的计划和组织能力、分析和解决问题的能力、团队合作的能力等。我深刻体会到,课程设计是一个综合能力的考验,需要综合运用各种技能和方法,才能取得好的结果。同时,我也意识到,课程设计是一个不断学习和提升的过程,需要不断反思和总结,不断改进和完善自己。

成功需要付出努力和坚持,不要轻易放弃。

创作不易,感谢各位的支持,你们的点赞和关注是我不竭创作动力哦!互帮互助,成长你我他,小小善举,请相信世界会变得更美好!

 创作不易,如对你有帮助可以请作者喝咖啡哦!谢谢!

 

这篇关于设计求解AOE网关键路径程序(详细设计,附完整实现代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/551342

相关文章

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

vscode保存代码时自动eslint格式化图文教程

《vscode保存代码时自动eslint格式化图文教程》:本文主要介绍vscode保存代码时自动eslint格式化的相关资料,包括打开设置文件并复制特定内容,文中通过代码介绍的非常详细,需要的朋友... 目录1、点击设置2、选择远程--->点击右上角打开设置3、会弹出settings.json文件,将以下内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

Java中List转Map的几种具体实现方式和特点

《Java中List转Map的几种具体实现方式和特点》:本文主要介绍几种常用的List转Map的方式,包括使用for循环遍历、Java8StreamAPI、ApacheCommonsCollect... 目录前言1、使用for循环遍历:2、Java8 Stream API:3、Apache Commons

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

MySQL分表自动化创建的实现方案

《MySQL分表自动化创建的实现方案》在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低,分表是一种有效的优化策略,它将数据分散存储在... 目录一、项目目的二、实现过程(一)mysql 事件调度器结合存储过程方式1. 开启事件调度器2. 创