图-拓扑排序

版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/83036085

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

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

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

首先创建图。

然后输出拓扑排序序列。

运行结果:

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

算法思想:

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]++;
	   }
}

猜你喜欢

转载自blog.csdn.net/baidu_38304645/article/details/83036085