数据结构,我真服了呀,这代码改如何写呢,令人头秃

img

能给出程序的详细注解嘛,我想理解明白点,用c语言来做,非常的感谢,好难

c语言实现

img

/*AOE-网的关键路径*/
# 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;
    }
}

/*顺序栈的存储结构*/
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;
        }
    }

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

    if (count < G.vexnum) {
        printf("该图存在回路!\n");
        return FALSE;
    }
    else
        return TRUE;
}

/*关键路径算法*/
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关键活动及对应的弧为:\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);
    return 0;
}


AOE网:关键路径和关键活动
https://download.csdn.net/download/dark_walker/12032098
https://blog.csdn.net/CocoWu892/article/details/82822300


//寻找图的关键路径 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
 
//最大边数,最大点数 
const int Max_M=100100;
const int Max_N=50100;
 
struct Graph
{
    int nodeNumber,Link[Max_N],number;
    struct node
    {
        int vertex,weight,next;
    }    edge[Max_M];
    void initGraph(int n=0)
    {
        number=n;
        nodeNumber=0;
        memset(Link,-1,sizeof(Link));
    }
    void addEdge(int vertex_x,int vertex_y,int weight)
    {
        edge[nodeNumber].vertex = vertex_y;
        edge[nodeNumber].weight = weight;
        edge[nodeNumber].next = Link[vertex_x];
        Link[vertex_x] = nodeNumber;
        nodeNumber++;
    }
    void eraseLink(int vertex)
    {
        Link[vertex] = -1;
    }
} ;
 
 
// 求图的拓扑序 
int topoOrder[Max_N],inDegree[Max_N];
bool topo(Graph &G, int *topoOrder)
{
    memset(inDegree,0,sizeof(inDegree));
    for (int i=0;i<G.number;i++)
    {
        for (int p=G.Link[i];p!=-1;p=G.edge[p].next)
            inDegree[G.edge[p].vertex]++;
    }
    
    queue<int> que;
    for (int i=0;i<G.number;i++)
        if (inDegree[i] == 0)
            que.push(i);
                
    int cnt=0;
    while (!que.empty())
    {
        int vertex = que.front();
        topoOrder[cnt++] = vertex;
        que.pop();
        
        for (int p=G.Link[vertex];p!=-1;p=G.edge[p].next)
        {
            if (--inDegree[G.edge[p].vertex] == 0)
                que.push( G.edge[p].vertex );
        }
    }
    
    return cnt == G.number;
}
 
//求图的关键路径 
 
 
//输出图的关键路径
int criPath[Max_N]; 
void findPrecusorNode(Graph &G, int vertex, int number)
{
    criPath[number] = vertex;
    //当前节点没有前驱节点,已经找到了一条关键路径 
    if (G.Link[vertex] == -1)
    {
        for (int i=number; i>0 ;i--)
            printf("%d ",criPath[i]);
        printf("%d\n",criPath[0]);
    }
    else
    {
        for (int p=G.Link[vertex]; p != -1; p=G.edge[p].next)
            findPrecusorNode(G, G.edge[p].vertex, number+1);
    }
}
 
int lastVis[Max_N];
Graph g;
void getCriticalPath(Graph &G, int *topoOrder)
{
    memset(lastVis,0,sizeof(lastVis));
    g.initGraph(G.number);
    for (int i=0; i<G.number; i++)
    {
        for (int p=G.Link[i]; p != -1; p=G.edge[p].next)
        {
            if ( lastVis[ G.edge[p].vertex ] < lastVis[i] + G.edge[p].weight )
            {
                lastVis[ G.edge[p].vertex ] = lastVis[i] + G.edge[p].weight;
                //更新前驱节点 
                g.eraseLink( G.edge[p].vertex);
                g.addEdge(G.edge[p].vertex, i, G.edge[p].weight);
            }
            else
            if ( lastVis[ G.edge[p].vertex ] == lastVis[i] + G.edge[p].weight )
                g.addEdge(G.edge[p].vertex, i, G.edge[p].weight);
        }
    }
    
    int Max_cost=0;
    for (int i=0; i<G.number; i++)
        Max_cost=max(Max_cost, lastVis[i]);
    
    printf("关键路径长度为:%d\n",Max_cost);            
    for (int i=0; i<G.number; i++)
        if (lastVis[i] == Max_cost)
        {
            // 输出关键路径
            findPrecusorNode(g,i,0); 
        }
}
int main()
{
    Graph G;
    //给定10个节点
    
    int n;
    puts("请输入点的数目:");
    scanf("%d",&n); 
    G.initGraph(n);
    puts("请输入边的数目:");
    int m,x,y,w;;
    scanf("%d",&m);
    printf("节点编号0 ~ %d\n",n-1); 
    puts("请输入边:(按格式 vertex_x vertex_y weight) ");
    for (int i=1; i<=m; i++)
    {
        scanf("%d%d%d",&x,&y,&w);
        G.addEdge(x,y,w);
    }
    
    if (topo(G, topoOrder))
        getCriticalPath(G,topoOrder);
    else
        puts("图中存在环,故不存在关键路径"); 
    return 0;
}