AOV网与拓扑排序

一.概念

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,成这样的有向图为顶点表示活动的网,简称AOV网(activity on vertex network)。最典型的例子是课程与课程之间的优先关系。

若某个AOV网中所有顶点都在拓扑序列中,说明该AOV网不存在回路。一个AOV网的拓扑序列可能不唯一。

对AOV网进行拓扑排序的基本思想是:

(1)从AOV网中选择一个没有前驱的顶点输出它;

(2)从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;

(3)重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。

显然,拓扑排序的结果有两种:AOV网中全部顶点都被输出,这说明AOV网中不存在回路;AOV网中顶点未被全部输出,剩余的顶点均不存在没有前驱的顶点,这说明AOV网中存在回路。

存储结构:

因为拓扑排序过程中需要查找所有以某个顶点为尾的弧,即需要找到该顶点的所有出边,所以,图应该采用邻接表存储。另外在拓扑排序过程中,需要对某顶点的入度进行操作,比如,查找入度等于零的顶点,将某顶点的入度减1等。而在一般图的邻接表对顶点入度的操作不方便,所以在顶点表中增加一个入度域,以方便对入度的操作。

二.代码

#include <stdio.h>
#include <malloc.h>

#define MaxNode 26

struct EdgeNode{
    int adjVertex;
    struct EdgeNode* next;
};

struct VertexNode{
    int in;
    char data;
    struct EdgeNode* firstEdge;
};

struct ALGraph{
    struct VertexNode adjList[MaxNode];
    int vertexAmount;
    int edgeAmount;
};

void initialize(struct ALGraph* graph, int vertexAmount, int edgeAmount){
    graph->vertexAmount = vertexAmount;
    graph->edgeAmount = edgeAmount;
    int i = 0;
    for(i = 0; i < MaxNode; i++){
        graph->adjList[i].in = 0;
        graph->adjList[i].data = 'A' + i;
        graph->adjList[i].firstEdge = NULL;
    }
}

void addEdge(struct ALGraph* graph, char prev, char next){
            struct EdgeNode* edgeNode = (struct EdgeNode*)malloc(sizeof(struct EdgeNode));
            edgeNode->adjVertex = next - 'A';
            edgeNode->next = NULL;

            int vertex = prev - 'A';
            if(graph->adjList[vertex].firstEdge == NULL){
                graph->adjList[vertex].firstEdge = edgeNode;
            } else {
                struct EdgeNode* tEdgeNode = graph->adjList[vertex].firstEdge;
                while(tEdgeNode->next != NULL){
                    tEdgeNode = tEdgeNode->next;
                }
                tEdgeNode->next = edgeNode;
            }
            
            graph->adjList[next - 'A'].in++;
}

void topSort(struct ALGraph graph){
    char outstr[MaxNode];
    int k = -1;

    int count = 0;

    int queue[MaxNode] = {0};
    int front = 0;
    int rear = -1;

    int i = 0;
    for(i = 0; i < graph.vertexAmount; i++){
        if(0 == graph.adjList[i].in){
            queue[++rear] = i;
        }
    }
    while(rear >= front){
        int vertexIndex = queue[front];
        outstr[++k] = graph.adjList[vertexIndex].data;
        struct EdgeNode* adjEdge = graph.adjList[vertexIndex].firstEdge;
        while(adjEdge){
            int tadjVex = adjEdge->adjVertex;
            graph.adjList[tadjVex].in--;
            count++;
            if(graph.adjList[tadjVex].in == 0){
                queue[++rear] = tadjVex;
            }
            adjEdge = adjEdge->next;
        }
        front++;
    }
    outstr[++k] = '\0';
    if(count < graph.vertexAmount){
        printf("%s\n", "circle exist!");
    } else {
        printf("%s\n", outstr);
    }
};

int main(){
    freopen("testData.txt", "r", stdin);
    int vertexAmount;
    int edgeAmount;
    while(scanf("%d%d", &vertexAmount, &edgeAmount)){
        if(0 == vertexAmount && 0 == edgeAmount){
            break;
        }        
        getchar();/*eat the '\n'*/

        /*initialize*/
        struct ALGraph graph;
        initialize(&graph, vertexAmount, edgeAmount);

        int i = 0;
        for(i = 0; i < edgeAmount; i++){
            char prev =  getchar();
            char next = getchar();
            getchar();/*eat the '\n'*/
            
            addEdge(&graph, prev, next);
        }
        topSort(graph);

    }
    return 0;
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/li4951/article/details/8177274
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞