最强解析-有向无环图的拓扑排序


/*
拓扑排序只适用于有向无环图 
拓扑排序规则如下:
(1) 从有向无环图中选择一个没有前驱(入度为0)的顶点vertex,并将顶点输出
(2)从图中删除这个顶点,同时删除从该顶点出发的所有边 
本文算法复杂度为 O(n+e); 
拓扑排序的结果不唯一。
2020/12/22 written by HL  
*/ 
#include<bits/stdc++.h>
using namespace std;
#define MAX_VERTEX_NUM 100 //最大矩阵维度 
typedef struct Arcnode//链表结点
{
	int adjvex; //该弧所指向的顶点在数组中的位置 
	struct Arcnode *next;//指向当前起点的下一条弧的指针 
 }Arcnode; 
 
typedef struct VertexNODE{
	int indegree;//存放入度个数 
	int data;//顶点域,存储顶点名称及坐标 
	Arcnode *firstnode; //指针域,指向顶点链表 
}vertexnode,Adjlist[MAX_VERTEX_NUM];//头结点

typedef struct{
	Adjlist adjlist;
	int n;//图中顶点数目 
	int e;//图中边的数目 
}GraphAdjList;//邻接表存储结构定义 

//使用邻接表存储有向图的创建
int  CreateGraph(GraphAdjList *G){//成功建立返回1,不成功返回0
	 int i,j,k;
	 int v1,v2;
	 Arcnode *newarc;
	 printf("\n输入有向图定点数和弧数vexnum,arcnum:");
	 scanf("%d%d",&G->n,&G->e);
	 if(G->n<0 || G->e<0){
	 	printf("\n顶点数或弧数不正确,有向图建立失败!\n");
	 	return 0;
	 } 
	 //初始化顶点信息
	 printf("\n输入%d个顶点:",G->n);
	 for(i=1;i<=G->n;i++){
	 	scanf("%d",&G->adjlist[i].data);
	 } 
	 //初始化链表部分信息
	 for(i=1;i<=G->n;i++){//邻接表初始化 
	 	G->adjlist[i].firstnode=NULL;
	 	G->adjlist[i].indegree=0;
	 } 
	 //初始化弧的信息
	 printf("\n\n输入%d条边:vi vj\n",G->e);//输入有向图的边
     for(k=0;k<G->e;k++){
     	scanf("%d%d",&v1,&v2);//v1 是起点, v2是终点
		 if(v1>G->n){
		 	printf("顶点%d不存在,有向图建立失败!\n",v1);
		 	return 0;
		 } 
     	 if(v2>G->n){
		 	printf("顶点%d不存在,有向图建立失败!\n",v2);
		 	return 0;
		 } 
		 newarc=(Arcnode*)malloc(sizeof(Arcnode));//头插法创建顶点链表
		 newarc->adjvex=v2;
		 if(G->adjlist[v1].firstnode==NULL){
		 	newarc->next=NULL;
		 	G->adjlist[v1].firstnode=newarc;
		 } 
		 else{
		 	newarc->next=G->adjlist[v1].firstnode->next;//fistnode 不存放真是顶点,不存放数据 
		 	G->adjlist[v1].firstnode->next=newarc;
		 }
		 G->adjlist[v2].indegree++;
	 }
	  printf("\n有向图建立成功!\n");
	  return 1; 
}
//拓扑排序,若GL无回路,则输出拓扑排序序列并返回0,有回路则返回-1
int TopologicalSort(GraphAdjList*G){
	int i,k,count;
	int e;
	Arcnode *p;
	queue<int>q;//定义队列
	for(i=1;i<=G->n;i++){//入度为0 入队列 
		if(!G->adjlist[i].indegree)
		    q.push(i); 
	}
    count=0;
    printf("\n其中一个拓扑排序序列为:\n");
    while(!q.empty()){
	    e=q.front();//输出入度为 0 的点
		q.pop(); 
    	printf("%d ",G->adjlist[e].data);
    	count++;  //对输出的顶点计数 
    	//遍历当前点的邻接点
		for(p=G->adjlist[e].firstnode;p!=NULL;p=p->next){
		    k=p->adjvex;//邻接点位置
			if(--G->adjlist[k].indegree==0){
				q.push(k);
			} 
		} 
	}
	printf("\n");
	if(count<G->n){
		printf("\n该有向图有回路,无法完成拓扑排序!\n");
		return -1;
	} 
	return 0;
} 

int main(){
	GraphAdjList H;
	CreateGraph(&H);
	TopologicalSort(&H);
	return 0; 
} 


  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值