/*
拓扑排序只适用于有向无环图
拓扑排序规则如下:
(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;
}
最强解析-有向无环图的拓扑排序
最新推荐文章于 2024-03-17 16:43:27 发布