美文网首页
图-拓扑排序

图-拓扑排序

作者: 如春天 | 来源:发表于2020-08-15 13:50 被阅读0次

    拓扑排序

    我们会把施工过程、生产流程、软件开发、教学安排等都当成一个项目工程来对待,所有的工程都可分为若干个活动的子工程。由这而来的图首先一定是一个无环图。而之前学习的最短路径问题和最小生成树问题是关于有环图的。

    在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系。这样的有向图为顶点表示活动的网,我们成为AOV网(Activity On Vertex Network )。AOV网中的弧表示活动之间存在某种制约关系,比如在学习数据结构这门课之前必须先学习C语言等等。这个场景在我们生活中很常见。

    拓扑排序的算法实现非常的简单,大体的思路就是用一个栈来存放所有入度为0的顶点,循环每次弹出栈顶入度为0的顶点并输出,然后更新它的邻接顶点的入度-1,如果它的邻接顶点更新后的入度为0就把它压入栈,循环往复,直到栈为空。倘若输出顶点数量<实际的顶点数量就表明图是一个有环的图,算法失败。因此也可以用该算法来判断图是否有环。
    对于此算法,我们用邻接表会更方便一点。
    /*
    邻接表结点结构: in(入度) data(顶点) firstEdge(第一个邻接点)
    */
    #include <stdlib.h>
    #include <stdio.h>
    #define OK 1
    #define ERROR 0
    #define Status int
    typedef struct EdgeNode 
    {
        int adjvex;/*邻接点域*/
        int weight;/*权值*/
        struct EdgeNode *next;
    }EdgeNode;
    
    typedef struct VertexNode
    {
        int in; /*入度*/
        int data;
        EdgeNode *firstEdge;
    }VertexNode, AdjvexList[MAXVEX];
    
    typedef struct 
    {
        AdjvexList adjList;
        int numVertexes, numEdges;
    }*GraphAdjList, graphAdjList;
    
    Status TopologicalSort(GraphAdjList G)
    {
        EdgeNode *e;
        int count;/*计数器:如果输出顶点数小于实际顶点数说明有环,拓扑排序则失败。反之则成功*/
        int getTop, i, k;/*getTop,临时存放栈顶弹出的值*/
        int *stack; /*初始化一个栈,用以存放入度为0的顶点*/
        int top; /*栈顶指针*/
        count = 0; top = 0;
        stack = (int *) malloc (sizeof(int) * G->numVertexes + 1); /*0 is not used*/
        for(i = 0; i < G->numVertexes; i++)
        {
            /*初始化遍历每个顶点,如果其入度为0则入。*/
            if(G->adjList[i].in == 0)
            {
                stack[++top] = i;
            }
        }
        while(top != 0)
        {
            /*栈不为空时,循环输出度为0的点,并且随时更新对应顶点的入度*/
            getTop = stack[top--];
            printf("%d->", G->adjList[getTop]);
            count++;/*输出从栈中 取出的度为0的顶点,打印他的值,顶点计数器+1*/
            for(e = G->adjList[i].firstEdge; e; e = e->next)
            {
                k = e->adjvex; /*取的相邻顶点的下标*/
                if(!(--G->adjList[k].in))
                {
                    /*先更新相邻顶点的入度,因为刚刚他的前驱顶点度为0被输出了,所以它的度-1,然后判断时候它的度也是0,如果是0的话则入栈*/
                    stack[++top] = k;
                }
            }
        }
        if(count != G->numVertexes)
        {
            return ERROR;
        }else
        {
            return OK;
        }
    }
    

    相关文章

      网友评论

          本文标题:图-拓扑排序

          本文链接:https://www.haomeiwen.com/subject/fxladktx.html