6-3 Topological Sort (25分)

Write a program to find the topological order in a digraph.

Format of functions:

bool TopSort( LGraph Graph, Vertex TopOrder[] );

where LGraph is defined as the following:

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{
    Vertex AdjV;
    PtrToAdjVNode Next;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];

typedef struct GNode *PtrToGNode;
struct GNode{  
    int Nv;
    int Ne;
    AdjList G;
};
typedef PtrToGNode LGraph;

The topological order is supposed to be stored in TopOrder[] where TopOrder[i] is the i-th vertex in the resulting sequence. The topological sort cannot be successful if there is a cycle in the graph – in that case TopSort must return false; otherwise return true.

Notice that the topological order might not be unique, but the judge’s input guarantees the uniqueness of the result.

Sample program of judge:

#include <stdio.h>
#include <stdlib.h>

typedef enum {false, true} bool;
#define MaxVertexNum 10  /* maximum number of vertices */
typedef int Vertex;      /* vertices are numbered from 0 to MaxVertexNum-1 */

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{
    Vertex AdjV;
    PtrToAdjVNode Next;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];

typedef struct GNode *PtrToGNode;
struct GNode{  
    int Nv;
    int Ne;
    AdjList G;
};
typedef PtrToGNode LGraph;

LGraph ReadG(); /* details omitted */

bool TopSort( LGraph Graph, Vertex TopOrder[] );

int main()
{
    int i;
    Vertex TopOrder[MaxVertexNum];
    LGraph G = ReadG();

    if ( TopSort(G, TopOrder)==true )
        for ( i=0; i<G->Nv; i++ )
            printf("%d ", TopOrder[i]);
    else
        printf("ERROR");
    printf("\n");

    return 0;
}

/* Your function will be put here */

Sample Input 1 (for the graph shown in the figure):

在这里插入图片描述

5 7
1 0
4 3
2 1
2 0
3 2
4 1
4 2

Sample Output 1:

4 3 2 1 0 

Sample Input 2 (for the graph shown in the figure):

在这里插入图片描述

5 8
0 3
1 0
4 3
2 1
2 0
3 2
4 1
4 2

Sample Output 2:

ERROR

源码:

int Indegree[MaxVertexNum];
bool TopSort( LGraph Graph, Vertex TopOrder[] )
{
    int count=0;
    //初始化Indegree
    for(int i=0;i<Graph->Nv;i++)
    {
        Indegree[i]=0;
    }
    for(int i=0;i<Graph->Nv;i++)
    {
        PtrToAdjVNode p=Graph->G[i].FirstEdge;
        while(p)
        {
            Indegree[p->AdjV]++;
            p=p->Next;
        }
    }
    //初始化栈
    int stack[MaxVertexNum];
    int f=-1;
    for(int i=0;i<Graph->Nv;i++)
    {
        if(!Indegree[i])
            stack[++f]=i;
    }
    //top
    while(f!=-1)
    {
        int t=stack[f--];
        TopOrder[count++]=t;
        PtrToAdjVNode p=Graph->G[t].FirstEdge;
        while(p)
        {
            if(--Indegree[p->AdjV]==0)
                stack[++f]=p->AdjV;
            p=p->Next;
        }
    }
    if(count<Graph->Nv)
        return false;
    else
        return true;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可能的实现,仅供参考: ```c #define MAX_VERTEX_NUM 100 // 最大顶点数 #define INF INT_MAX // 定义正无穷 typedef struct EdgeNode { int adjvex; // 邻接点下标 int weight; // 权值 struct EdgeNode *next; // 指向下一条边的指针 } EdgeNode; typedef struct VertexNode { int data; // 顶点的数据 EdgeNode *firstedge; // 指向第一条边的指针 } VertexNode; typedef struct { VertexNode adjlist[MAX_VERTEX_NUM]; // 邻接表 int vexnum, arcnum; // 顶点数和边数 } ALGraph; // 拓扑排序 int TopologicalSort(ALGraph *G, int *etv) { int i, j, k, count; int indegree[MAX_VERTEX_NUM]; // 入度数组 int stack[MAX_VERTEX_NUM]; // 栈 int top = -1; // 栈顶指针 for (i = 0; i < G->vexnum; i++) { indegree[i] = 0; // 初始化入度数组 } // 统计每个顶点的入度 for (i = 0; i < G->vexnum; i++) { EdgeNode *p = G->adjlist[i].firstedge; while (p != NULL) { indegree[p->adjvex]++; p = p->next; } } // 将入度为0的顶点入栈 for (i = 0; i < G->vexnum; i++) { if (indegree[i] == 0) { stack[++top] = i; } } count = 0; // 计数器,记录输出的顶点数 while (top != -1) { i = stack[top--]; // 弹出一个入度为0的顶点 printf("%d ", i); // 输出该顶点 count++; // 更新与该顶点相邻的顶点的入度 EdgeNode *p = G->adjlist[i].firstedge; while (p != NULL) { k = p->adjvex; if (--indegree[k] == 0) { stack[++top] = k; } if (etv[i] + p->weight > etv[k]) { etv[k] = etv[i] + p->weight; } p = p->next; } } if (count < G->vexnum) { return 0; // 拓扑排序失败,有环 } else { return 1; // 拓扑排序成功,无环 } } // 关键路径算法 void CriticalPath(ALGraph *G) { int i, j, k; int etv[MAX_VERTEX_NUM]; // 事件最早发生时间 int ltv[MAX_VERTEX_NUM]; // 事件最晚发生时间 int stack[MAX_VERTEX_NUM]; // 栈 int top = -1; // 栈顶指针 EdgeNode *p; // 初始化事件最早发生时间 for (i = 0; i < G->vexnum; i++) { etv[i] = 0; } // 拓扑排序,计算事件最早发生时间 if (!TopologicalSort(G, etv)) { printf("Error: the graph has a cycle.\n"); return; } // 初始化事件最晚发生时间 for (i = 0; i < G->vexnum; i++) { ltv[i] = etv[G->vexnum - 1]; } // 逆拓扑排序,计算事件最晚发生时间 while (top != -1) { i = stack[top--]; p = G->adjlist[i].firstedge; while (p != NULL) { k = p->adjvex; if (ltv[k] - p->weight < ltv[i]) { ltv[i] = ltv[k] - p->weight; } p = p->next; } } // 计算每条边的最早开始时间和最晚开始时间,找出关键路径 for (i = 0; i < G->vexnum; i++) { p = G->adjlist[i].firstedge; while (p != NULL) { j = p->adjvex; int e = etv[i]; // 最早开始时间 int l = ltv[j] - p->weight; // 最晚开始时间 if (e == l) { // 该边属于关键路径 printf("Criticalpath: <%d,%d> length: %d\n", i, j, p->weight); } p = p->next; } } } int main() { ALGraph G; // 构造有向图 G.vexnum = 10; G.arcnum = 12; for (int i = 0; i < G.vexnum; i++) { G.adjlist[i].data = i; G.adjlist[i].firstedge = NULL; } int edges[][3] = {{0, 1, 3}, {0, 2, 4}, {1, 3, 5}, {1, 4, 6}, {2, 3, 8}, {2, 4, 7}, {3, 5, 9}, {3, 6, 11}, {4, 6, 10}, {5, 7, 13}, {6, 7, 12}, {7, 8, 5}}; for (int i = 0; i < G.arcnum; i++) { int u = edges[i][0], v = edges[i][1], w = edges[i][2]; EdgeNode *p = (EdgeNode *) malloc(sizeof(EdgeNode)); p->adjvex = v; p->weight = w; p->next = G.adjlist[u].firstedge; G.adjlist[u].firstedge = p; } // 输出关键路径 CriticalPath(&G); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值