图-拓扑排序

由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

顶点表活动,弧表示活动间先后依赖关系的有向图。

用以表示工程或系统的施工计划,可据此判断工程是否可以顺利进行。网中应存在一覆盖全部顶点的序列(全序),在该序列中顶点出现的顺满足网中的先后顺序(偏序)。一个全序就对应一个合法的完整工程。

输入:创建图。

输出:拓扑排序序列。

《图-拓扑排序》

运行结果:

《图-拓扑排序》

若得到一个含全部顶点的拓扑有序序列则说明工程可顺利开展,不存在则说明图中存在有向回路,不合理。

算法思想:

1、从有向图中选取一没有前驱的顶点输出之;

2、从图中删除此顶点即所有从其出发的弧。

3、重复上述两步,至图空,或图不空但不存在无前驱的顶点(得一有向环).

实现的话,入度0顶点入栈,{删除{出栈并据此更新入度},零入度者入栈}重复至栈空,若弹出的 元素个数小于顶点数说明存在回路。计划不合理。

算法实现:

邻接表存储:

Status TopologicalSort(MGraph G,SqStack &T){
    /*拓扑排序
    将度为0的顶点的入队 出队 更新后继点入度 若入度为0 则入队
    根据输出结点数量判断是否合理
    各点ve初始化为0 计算入度 求各顶点最早到达时间计入全局数组ve*/
    int InDegree[MVNUM],i,count=0,j; //count对输出的点进行计数
    bool a[MVNUM]; //判断顶点是否输出过
    LinkQueue Q;
    InitQueue(Q);
    InitStack(T);
    memset(InDegree,0,sizeof(InDegree));
	
    memset(a,0,sizeof(a));
    FindInDegree(G,InDegree);
    for(i=0;i<G.vexnum;i++){
        if(!InDegree[i]){
	    EnQueue(Q,i);
	    a[i]=TRUE;
	}
    }
    while(!QueueEmpty(Q)){
        DeQueue(Q,i);
        Push(T,i);
	OutPutElem(G.vexs[i]);
        count++;
        for(j=0;j<G.vexnum;j++){
	    if(G.arcs[i][j].adj!=INFINITY){ //如果有弧
	        InDegree[j]--;
            }
	    if(!a[j]&&!InDegree[j]) {
		EnQueue(Q,j);
	        a[j]=TRUE;
	    }
        } 
    }  
    if(count==G.vexnum)
        return OK;
    else
        return ERROR;
}

计算各项点的入度.

void FindInDegree(MGraph G,int InDegree[MVNUM]){
    //计算各项点的入度
    for(int i=0;i<G.vexnum;i++)
       for(int j=0;j<G.vexnum;j++)
           if(G.arcs[j][i].adj!=INFINITY)
	      InDegree[i]++;
}

邻接表存储

Status TopologicalSort(ALGraph G,SqStack &T){
    /*拓扑排序
    将度为0的顶点入队 出队 更新后继结点的入度 若入读为0 则入队
    根据输出结点数量判断是否合理
    各点ve初始化为0 计算入度 求各顶点最早到达时间计入全局数组ve*/
    int InDegree[MVNUM],i,k,count=0; //count对输出的结点进行计数
    memset(InDegree,0,sizeof(InDegree));
       FindInDegree(G,InDegree);
    LinkQueue Q;
    InitQueue(Q);
    InitStack(T);
    for(i=0;i<G.vexnum;i++){
       if(!InDegree[i])
           EnQueue(Q,i);
    }
    while(!QueueEmpty(Q)){
       DeQueue(Q,i);
       Push(T,i);
       count++;
       OutPutElem(G.vertices[i].data);
       for(ArcNode *p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc){
           k=p->adjvex;
	   InDegree[k]--;
           if(!InDegree[k])
	       EnQueue(Q,k);
       }
   }
   if(count==G.vexnum)
       return OK;
   else
       return ERROR;
}

计算各个结点的入度.

void FindInDegree(ALGraph G,int InDegree[]) {
   //计算各个结点的入度
   int k,i;
   for(i=0;i<G.vexnum;i++)
       for(ArcNode *p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc){
	    k=p->adjvex;
	    InDegree[k]++;
       }
}

 

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