拓扑排序算法

  • 什么是拓扑排序

对一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。

  • 背景知识

一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程的开始是以它的所有前序子工程的结束为先决条件的,但有些子工程没有先决条件,可以安排在任何时间开始。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。

  • 算法大致思想

    由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。

    1. 选择一个入度为0的顶点并输出之;
    2. 从网中删除此顶点及所有出边。
    3. 循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列

    c/c++代码实现

#include <iostream>
#include<stdlib.h>
#define maxSize 100
typedef struct EdgeNode{//边结点 
    int adjvex;
    struct EdgeNode* next;
}EdgeNode; 

typedef struct Vnode{//顶点结点 
    int data;
    int in;//新增的入度个数 
    EdgeNode *firstEdge;    
}Vnode,Adjvex[maxSize];

typedef struct AGraph{//图结点 
    Adjvex adjvex;
    int n,e;
}AGraph;

void createGraph(AGraph &G){//邻接表创建图 
    EdgeNode *p;
    int i,j,k;
    printf("请输入图的顶点数和边数\n");
    scanf("%d %d",&G.n,&G.e); 
    printf("请输入图的顶点\n");
    for(i=0;i<G.n;i++){//输入图的顶点 
        scanf("%d",&G.adjvex[i]);
        G.adjvex[i].firstEdge=NULL;
        G.adjvex[i].in=0;//所有的顶点入度初始化为0 
    }

    printf("请输入边的下标i j\n");
    for(k=0;k<G.e;k++){//输入图的边 
        scanf("%d %d",&i,&j);
        p=(EdgeNode *)malloc(sizeof(EdgeNode));
        p->adjvex=j;
        p->next=G.adjvex[i].firstEdge;
        G.adjvex[i].firstEdge=p;
        G.adjvex[j].in++; //j顶点入度自增长 
    }
}

int topSort(AGraph G){//拓扑排序 
    EdgeNode *p;
    int i,j,k,count=0;
    int *que;//栈里面存放的是顶点下标 
    que=(int *)malloc(G.n*sizeof(int));
    int top=-1;//创建并初始化栈 
    for(i=0;i<G.n;i++){
        if(!G.adjvex[i].in){//若入度为0的,则入栈 
            que[++top]=i;
        }
    }
    while(top!=-1){//若栈不为空 
        k=que[top--];//栈顶出栈 
        printf("%d ",G.adjvex[k].data);
        count++;//计数访问了多少顶点 
        for(p=G.adjvex[k].firstEdge;p!=NULL;p=p->next){//遍历出栈顶点的边表 
            G.adjvex[p->adjvex].in--;//与之相邻接的顶点的入度自减 
            if(G.adjvex[p->adjvex].in==0){//把自减后入度为0的顶点入栈 
                que[++top]=p->adjvex;
            }
        } 
    }
    if(count<G.n){//若有顶点未访问到,则拓扑排序失败 
        return 0;
    }else{
        return 1;
    }
}
int main(int argc, char** argv) {
    AGraph G;
    createGraph(G);
    topSort(G);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37597859/article/details/79874828