C语言实现有向无环图的拓扑排序算法
2017-08-03 16:31
169 查看
对AOV网进行拓扑排序的基本思路是:从AOV网中选择一个入度为0的顶点输出,然后删除此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者在AOV网中不存在入度为0的顶点为止。
这里图使用的数据结构是邻接表,并且在顶点表加入顶点入度一项。
以下程序在DEV C++中编译运行通过。
#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 20
typedef struct EdgeNode
{
int adjvex;//邻接点域,存储该顶点对应的下标
struct EdgeNode *next;//链域,指向下一个邻接点
}EdgeNode;
typedef struct VertexNode
{
int in;//顶点入度
char data;//顶点域,存储顶点信息
EdgeNode *firstedge;//边表头指针
}VertexNode,AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes,numEdges;
}GraphAdjList;
void CreateALGraph(GraphAdjList *G)
{
int i,j,k;
EdgeNode *e;
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numVertexes,&G->numEdges);
getchar();
for(i=0;i<G->numVertexes;i++)
{
printf("输入第%d个顶点的值和入度:\n",i+1);
scanf("%c,%d",&G->adjList[i].data,&G->adjList[i].in);
G->adjList[i].firstedge=NULL;
getchar();
}
for(k=0;k<G->numEdges;k++)
{
printf("输入第%d条有向边(vi,vj)上的顶点序号:\n",k+1);
scanf("%d,%d",&i,&j);
e=(EdgeNode*)malloc(sizeof(EdgeNode));
e->adjvex=j;
e->next=G->adjList[i].firstedge;
G->adjList[i].firstedge=e;
}
}
int TopologicalSort(GraphAdjList *G)
{
EdgeNode *e;
int i,k,gettop;
int top=0;//用于栈指针下标
int count=0;//用于统计输出顶点的个数
int *Stack;//建栈存储入度为0的指针
Stack=(int*)malloc(G->numVertexes*sizeof(int));
for(i=0;i<G->numVertexes;i++)
{
if(G->adjList[i].in==0)
Stack[++top]=i;//将入度为0的顶点的序号入栈
}
while(top!=0)
{
gettop=Stack[top--];
printf("%c->",G->adjList[gettop].data);
count++;
for(e=G->adjList[gettop].firstedge;e;e=e->next)
{
//对此顶点的弧表进行遍历
k=e->adjvex;//邻接点的序号
if(!(--G->adjList[k].in))
Stack[++top]=k;
}
}
if(count<G->numVertexes)
return -1;
else
return 0;
}
void main()
{
GraphAdjList G;
int flag;
CreateALGraph(&G);
flag=TopologicalSort(&G);
if(flag==-1)
printf("该有向图存在环,构造拓扑序列失败!\n");
else if(flag==0)
printf("构造拓扑序列成功!\n");
}
运行结果如图所示。
求出的结果不是唯一的拓扑排序方案。
整个算法的时间复杂度为O(n+e),n是顶点数,e是边数。
这里图使用的数据结构是邻接表,并且在顶点表加入顶点入度一项。
以下程序在DEV C++中编译运行通过。
#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 20
typedef struct EdgeNode
{
int adjvex;//邻接点域,存储该顶点对应的下标
struct EdgeNode *next;//链域,指向下一个邻接点
}EdgeNode;
typedef struct VertexNode
{
int in;//顶点入度
char data;//顶点域,存储顶点信息
EdgeNode *firstedge;//边表头指针
}VertexNode,AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numVertexes,numEdges;
}GraphAdjList;
void CreateALGraph(GraphAdjList *G)
{
int i,j,k;
EdgeNode *e;
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numVertexes,&G->numEdges);
getchar();
for(i=0;i<G->numVertexes;i++)
{
printf("输入第%d个顶点的值和入度:\n",i+1);
scanf("%c,%d",&G->adjList[i].data,&G->adjList[i].in);
G->adjList[i].firstedge=NULL;
getchar();
}
for(k=0;k<G->numEdges;k++)
{
printf("输入第%d条有向边(vi,vj)上的顶点序号:\n",k+1);
scanf("%d,%d",&i,&j);
e=(EdgeNode*)malloc(sizeof(EdgeNode));
e->adjvex=j;
e->next=G->adjList[i].firstedge;
G->adjList[i].firstedge=e;
}
}
int TopologicalSort(GraphAdjList *G)
{
EdgeNode *e;
int i,k,gettop;
int top=0;//用于栈指针下标
int count=0;//用于统计输出顶点的个数
int *Stack;//建栈存储入度为0的指针
Stack=(int*)malloc(G->numVertexes*sizeof(int));
for(i=0;i<G->numVertexes;i++)
{
if(G->adjList[i].in==0)
Stack[++top]=i;//将入度为0的顶点的序号入栈
}
while(top!=0)
{
gettop=Stack[top--];
printf("%c->",G->adjList[gettop].data);
count++;
for(e=G->adjList[gettop].firstedge;e;e=e->next)
{
//对此顶点的弧表进行遍历
k=e->adjvex;//邻接点的序号
if(!(--G->adjList[k].in))
Stack[++top]=k;
}
}
if(count<G->numVertexes)
return -1;
else
return 0;
}
void main()
{
GraphAdjList G;
int flag;
CreateALGraph(&G);
flag=TopologicalSort(&G);
if(flag==-1)
printf("该有向图存在环,构造拓扑序列失败!\n");
else if(flag==0)
printf("构造拓扑序列成功!\n");
}
运行结果如图所示。
求出的结果不是唯一的拓扑排序方案。
整个算法的时间复杂度为O(n+e),n是顶点数,e是边数。
相关文章推荐
- 【C语言】模拟实现库函数strcat函数
- C语言实现双向链表[上]
- C语言指针实现排序算法
- C语言可变参数的实现详解
- (C语言)队列的链式实现(数据结构十一)
- Linux下C语言实现查看进程是否存在
- 扫雷游戏(C语言实现)
- C语言实现密码输入
- 二叉树的创建和遍历-C语言实现
- linux网络编程:用C语言实现的聊天程序(异步通信)
- 用C语言实现 函数重载
- 【c++版数据结构】之用c语言实现静态链表
- 【Linux】C语言实现文件夹拷贝
- 冒泡排序(c语言实现)
- 栈和队列 C语言实现
- 十字链表的c语言实现
- C语言中可变参数函数实现原理
- 基于ARP的局域网IP劫持——C语言实现
- android j使用JNI实现ava语言调用C语言
- LeetCode-18-4Sum(C语言实现)