【数据结构课程设计】关键路径问题

这篇具有很好参考价值的文章主要介绍了【数据结构课程设计】关键路径问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 问题描述与功能需求分析

1.1问题描述

1) 任务:设计一个程序求出完成整项工程至少需要多少时间以及整项工程中的关键活动。

2)基本要求:

(1)对一个描述工程的 AOE 网,应判断其是否能够顺利进行。

(2)若该工程能顺利进行,输出完成整项工程至少需要多少时间,以及每一个关键活动所依附的两个顶点、最早发生时间、最迟发生时间。

1.2 功能需求分析

1、用邻接表存储一张带权有向图。

2、对图进行拓扑排序,并进行事件的最早发生时间Ve[i]的计算。

3、根据排序结果,判断图中是否存在有向环。

4、根据逆拓扑序列,计算事件的最晚发生时间Vl[i]。

5、计算活动的最早、最晚发生时间,判断关键活动,找出关键路径。

2 概要设计

2.1 模块简介

依据程序的功能模块的划分,各模块定义如下:

(1);创建邻接表

 int CreateAdjList(AdjList* G)

用邻接表的算法来建立图,在邻接表的顶点增加一项数据为入度,用来保存每个结点的入度。通过遍历邻接表可以将每个元素的入度求出。

(2);拓扑排序

int TopoSort(AdjList G,SeqStack* T)

在拓扑排序过程中,求顶点的 Ve[i],将得到的拓扑序列进栈。

(3);关键路径求解

 voidCriticalPath(AdjList G, SeqStack* T)

根据各顶点的ve和vl值,求每条弧s的最早开始时间e(s)和最迟开始时间l(s)。若某条弧满足条件e(s) = l(s),则为关键活动。

3 详细设计

3.1 数据结构

//弧结点结构
typedef struct ArcNode {
    int adjvex;                            //该弧指向顶点的位置
    struct ArcNode* nextarc;                //指向下一条弧的指针
    int activity;                            //弧表示的活动
    int weight;                            //权值
}ArcNode;


//表头结点结构
typedef struct VertexNode {
    VertexData data;                        //顶点数据
    ArcNode* firstarc;                    //指向该顶点的第一条弧的指针
}VertexNode;



//邻接表结构
typedef struct {
    VertexNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnum;                    //图的顶点数和弧数
}AdjList;

3.2 算法分析与实现

# include<stdio.h>
# include<malloc.h>
# define MAX_VERTEX_NUM 20
# define TRUE 1
# define FALSE 0

/*AOE-网的邻接表表示法*/
typedef char VertexData;

//弧结点结构
typedef struct ArcNode {
    int adjvex;                                //该弧指向顶点的位置
    struct ArcNode* nextarc;                //指向下一条弧的指针
    int activity;                            //弧表示的活动
    int weight;                                //权值
}ArcNode;

//表头结点结构
typedef struct VertexNode {
    VertexData data;                        //顶点数据
    ArcNode* firstarc;                        //指向该顶点的第一条弧的指针
}VertexNode;

//邻接表结构
typedef struct {
    VertexNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnum;                        //图的顶点数和弧数
}AdjList;

/*求顶点位置*/
int LocateVertex(AdjList* G, VertexData v) {
    int k;
    for (k = 0; k < G->vexnum; k++) {
        if (G->vertex[k].data == v)
            break;
    }
    return k;
}

/*创建AOE-网的邻接表*/
int CreateAdjList(AdjList* G) {
    int i, j, k, activity, weight;
    VertexData v1, v2;
    ArcNode* p;
    printf("输入图的顶点数和弧数:");            //输入图的顶点数和弧数
    scanf("%d%d", &G->vexnum, &G->arcnum);
    printf("输入图的顶点:");
    for (i = 0; i < G->vexnum; i++) {            //输入图的顶点,初始化顶点结点
        scanf(" %c", &(G->vertex[i].data));
        G->vertex[i].firstarc = NULL;
    }
    for (k = 0; k < G->arcnum; k++) {
        printf("输入第%d条弧的两个顶点、弧表示的活动及权值:", k + 1);
        scanf(" %c %c %d %d", &v1, &v2, &activity, &weight);    //输入一条弧的两个顶点、弧表示的活动及权值
        i = LocateVertex(G, v1);
        j = LocateVertex(G, v2);
        p = (ArcNode*)malloc(sizeof(ArcNode));    //申请新弧结点
        p->activity = activity;
        p->weight = weight;
        p->adjvex = j;
        p->nextarc = G->vertex[i].firstarc;
        G->vertex[i].firstarc = p;
        getchar();
    }
}

/*顺序栈的存储结构*/
typedef struct {
    int elem[MAX_VERTEX_NUM];            //用于存放栈中元素的一维数组
    int top;                            //存放栈顶元素的下标,top为-1表示空栈
}SeqStack;

/*初始化顺序栈*/
void InitStack(SeqStack* S) {
    S->top = -1;
}

/*判空*/
int IsEmpty(SeqStack* S) {
    if (S->top == -1)                    //栈为空
        return TRUE;
    else
        return FALSE;
}

/*顺序栈进栈*/
int Push(SeqStack* S, int x) {
    if (S->top == MAX_VERTEX_NUM - 1)    //栈已满
        return FALSE;
    S->top++;
    S->elem[S->top] = x;                //x进栈
    return TRUE;
}

/*顺序栈出栈*/
int Pop(SeqStack* S) {
    if (S->top == -1)                    //栈为空
        return FALSE;
    S->top--;
    return TRUE;
}

int indegree[MAX_VERTEX_NUM];            //存放各顶点入度数
int ve[MAX_VERTEX_NUM];                    //各顶点的最早发生时间

/*求各顶点入度算法*/
void FindID(AdjList G) {
    int i;
    ArcNode* p;
    for (i = 0; i < G.vexnum; i++)
        indegree[i] = 0;
    for (i = 0; i < G.vexnum; i++) {
        p = G.vertex[i].firstarc;
        while (p != NULL) {
            indegree[p->adjvex]++;
            p = p->nextarc;
        }
    }
}

/*拓扑排序,求逆拓扑序列及事件最早发生时间ve(i)*/
int TopoSort(AdjList G, SeqStack* T) {    //栈T用于生成逆拓扑序列
    int i, k, count = 0;
    SeqStack S;                            //栈S用于存放入度为0的顶点
    ArcNode* p;
    FindID(G);                            //求各顶点入度
    InitStack(T);                        //初始化栈T
    InitStack(&S);                        //初始化栈S
    for (i = 0; i < G.vexnum; i++) {
        if (indegree[i] == 0)
            Push(&S, i);                //将入度为0的顶点入栈S
    }
    for (i = 0; i < G.vexnum; i++)
        ve[i] = 0;                        //初始化最早发生时间
    while (!IsEmpty(&S)) {
        i = S.elem[S.top];
        Pop(&S);
        count++;
        Push(T, i);                        //按拓扑顺序进入栈T
        p = G.vertex[i].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            indegree[k]--;                //i号顶点的每个邻接点的入度减1
            if (indegree[k] == 0)
                Push(&S, k);            //若入度减为0则入栈
            if (ve[i] + p->weight > ve[k])    //按拓扑顺序计算事件最早发生时间
                ve[k] = ve[i] + p->weight;
            p = p->nextarc;
        }
    }
     if (count < G.vexnum) {
        printf("该图存在回路!\n");
        return;
    }
     else

    printf("\n事件最早发生时间为:");    //输出事件的最早发生时间
    for (i = 0; i < G.vexnum; i++)
        printf("%d ", ve[i]);

}

/*关键路径算法*/
void CriticalPath(AdjList G, SeqStack* T) {
    ArcNode* p;
    int i, j, k, dut, ei, li;
    char tag;
    int vl[MAX_VERTEX_NUM];                //每个顶点的最迟发生时间
    TopoSort(G, T);                        //① 求事件最早发生时间和逆拓扑序列栈T
    for (i = 0; i < G.vexnum; i++)
        vl[i] = ve[G.vexnum - 1];        //将各事件的最晚发生时间初始化为汇点的最早发生时间
    while (!IsEmpty(T)) {                //② 按逆拓扑顺序求各顶点的最晚发生时间vl值
        j = T->elem[T->top];
        Pop(T);
        p = G.vertex[j].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            dut = p->weight;
            if (vl[k] - dut < vl[j])
                vl[j] = vl[k] - dut;
            p = p->nextarc;
        }
    }

    printf("\n事件最晚发生时间为:");    //输出事件的最晚发生时间
    for (i = 0; i < G.vexnum; i++)
        printf("%d ", vl[i]);
    printf("\n最少花费时间为:%d \n",ve[G.vexnum-1]); 
    printf("关键活动及对应的弧为:\n");
    for (j = 0; j < G.vexnum; j++) {    //③ 求各活动的最早开始时间ei和最晚开始时间li
        p = G.vertex[j].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            dut = p->weight;
            ei = ve[j];
            li = vl[k] - dut;
            if (ei == li)                //④ 输出关键活动及对应的路径
                printf("a%d v%c->v%c\n", p->activity, G.vertex[j].data, G.vertex[k].data);
            p = p->nextarc;
            
        }
    }
}

int main() {
    AdjList G;
    SeqStack T;
    CreateAdjList(&G);
    CriticalPath(G, &T);
    getchar();
    return 0;
}

运行结果(以此题为例)

【数据结构课程设计】关键路径问题
【数据结构课程设计】关键路径问题
【数据结构课程设计】关键路径问题

4 总结

在求关键路径的算法中,在求每一个事件的最早最迟发生时间,以及活动得到最早和最迟开始时,都要对所有顶点及每一个顶点边表中的边结点进行检查,因此求关键路径的时间复杂度为O(n+e)


~禁止转载~

文章来源地址https://www.toymoban.com/news/detail-497255.html

到了这里,关于【数据结构课程设计】关键路径问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构拓扑排序以及关键路径(出度邻接表)C语言 完整代码

    现实生活中一项工程通常会拆分成多个部分来进行,这些部分有些相互之间有发生的前提关系,还有些可以同时发生且不会互相打扰,但是合理且充分的利用时间来完成项目是一个问题。在项目完成的过程中,那些项目的完成时间被压缩可以压缩工程的总时间,以便于提高整

    2024年02月04日
    浏览(36)
  • 数据结构课程设计

    编制一个能演示执行集合的交、并和差运算的程序。 要求: 集合元素用小写英文字母,执行各种操作应以对话方式执行。 算法要点:利用单链表表示集合;理解好三种运算的含义 分析 : 输入:输入应该具有判断是否为小写字母的功能,如果不是小写字母,应该舍去,同时

    2024年02月02日
    浏览(34)
  • 数据结构第12周 :( 有向无环图的拓扑排序 + 拓扑排序和关键路径 + 确定比赛名次 + 割点 )

    【问题描述】 由某个集合上的一个偏序得到该集合上的一个全序,这个操作被称为拓扑排序。偏序和全序的定义分别如下:若集合X上的关系R是自反的、反对称的和传递的,则称R是集合X上的偏序关系。设R是集合X上的偏序,如果对每个x,y∈X必有xRy或yRx,则称R是集合X上的全序

    2024年02月08日
    浏览(31)
  • 数据结构课程设计 ——考试报名系统

    数据结构课程设计 ——考试报名系统 一、项目功能要求 完成对考生信息的建立,查找,插入,修改,删除等功能。其中考生信息包括准考证号,姓名,性别,年龄和报考类别等信息。项目在设计时应首先确定系统的数据结构,定义类的成员变量和成员函数;然后实现各成员

    2024年02月04日
    浏览(36)
  • 数据结构课程设计1: 区块链

    1.任务: [问题描述] 使用链表设计一个保存信息的系统,该系统拥有类似区块链的设计以防止信息被轻易篡改。 该题目使用一个链表。信息保存在链表的每一个节点中,每个节点需要包含该节点的编号、信息和校验码。其中: + 每个节点的编号按照顺序递增,从0开始。 + 节

    2023年04月16日
    浏览(95)
  • 数据结构课程设计 仓储管理系统

    【基本功能】 把货品信息表抽象成一个线性表,货品信息(包括ID、货品名、定价、数量等)作为线性表的一个元素,实现:按ID、货品名分别查找某货品信息(包括ID、货品名、定价、数量等);收录货品(如果货品在帐中已有,则只将总库存量增加。否则插入新增信息);

    2024年01月23日
    浏览(43)
  • 一、课程设计目的与任务《数据结构》课程设计是为训练学生的数据组织能力和提高程序设计能力而设置的增强实践能力的课程。目的:学习数据结构课程,旨在使学生学会分析研究数据对象的特性,学会数据的组织方法,以

    一、课程设计目的与任务 《数据结构》课程设计是为训练学生的数据组织能力和提高程序设计能力而设置的增强实践能力的课程。目的:学习数据结构课程,旨在使学生学会分析研究数据对象的特性,学会数据的组织方法,以便选择合适的数据的逻辑结构和存储结构以及相应

    2024年02月21日
    浏览(42)
  • 【数据结构课程设计】简单搜索引擎系统

    该程序使用python语言实现利用爬虫代码爬取网站链接信息,将网站中文词语通过结巴分词进行分割,并存储爬取的数据信息,利用结巴分词库处理输入框用户输入的词语,进行搜索,通过链接评价函数,优先显示评分较高的链接;设计简单的html页面,实现可视化搜索功能。

    2024年01月23日
    浏览(43)
  • 数据结构课程设计——项目2:校园导游咨询

    【问题描述】 设计一个校园导游程序,为来访的客人提供各种信息查询服务。 【基本要求】 设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校 内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。 为来访客人提供图中任

    2024年02月02日
    浏览(53)
  • 数据结构课程设计:学生成绩管理系统

    目  录 第一章   需求分析 第二章 概要设计 第三章 详细设计 第四章 测试报告 第五章 安装及使用 第六章 项目总结 第七章 源码 一.需求分析        学生成绩管理是一个学校不可缺少的部分,它的内容对于学校的管理者和学生以及学生家长来说都至关重要,所以一个良好

    2024年02月02日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包