C语言利用图的邻接矩阵的存储方式实现拓扑排序
在拓扑排序中,我们的对象是有向无环图,这种图是描述工程进行过程的有效工具。比如“课程开课顺序,施工进程,软件开发进程”,我们在使用有向无环图表示他们的时候,我们往往使用顶点表示这些事件中的一个活动,顶点和顶点之间的有向边表示一种活动和活动之间的先后顺序。
如上就是一种有向无环图,比如在活动c1进行完成之后,c8、c3才可以开始进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
那么我们怎么把,这个网,按照活动之间的先后顺序进行输出呢?比如:
Description
图采用邻接表为存储结构,图中的顶点数为n(0<n<=20),n个顶点的信息依次为 0,1,...,n-1。采用邻接表存储,编写程序输出该图的拓扑序列 。
要求:入度为零的顶点用栈存储。
Input
输入数据:
第1行:顶点数,弧数
第2行开始,每行输入一个顶点偶对,例如:vi,vj
Output
输出数据:
以空格分隔的拓扑序列,如果存在环,则输出空或者部分顶点。
Sample Input
6,8
0,1
0,2
0,3
2,1
2,4
3,4
5,3
5,4
Sample Output
5 0 2 1 3 4
想要输出5 0 2 1 3 4这个顺序:我们需要做的如下步骤。
获取这个图的所有顶点的入度,存入一个stack(栈)/或者队列,便于动态的存取顶点;
删除入度为0的顶点,并把关联的顶点的入度-1,输出这个删除的顶点;
-1之后,再次检查图中是否有入度为0的顶点;
下面是预编译文件和结构体,我们需要声明一个邻接矩阵和栈;
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 30
#define Max_Vetex_Num 100
typedef struct {
int vexs[Max_Vetex_Num];
int arcs[Max_Vetex_Num][Max_Vetex_Num];
int vexnum,arcnum;
}Mgraph;
typedef struct{
int *base;
int *top; //栈顶指针
int size;
}seqStack;
关于栈的操作,我在最后会贴上代码,分别是初始化,入栈,出栈,检空等...
然后就是关于拓扑排序的函数操作,我们需要两个函数,1.获取所有的入度,2.对这些入度为0的顶点进行删除和入度-1等操作。
void FindIndegree(Mgraph *G,int indegree[])
{
int i;
int j;
for(i = 0;i<G->vexnum ;i++)
{
for(j= 0;j<G->vexnum;j++)
{
if(G->arcs[j][i]==1){
indegree[i]++;
}
}
}/*for*/
}/*end*/
void TopSort(Mgraph *G){
int i,j,k;
int count;
int indegree[G->vexnum];
for(i = 0;i<G->vexnum ;i++)
{
indegree[i] = 0;
}
FindIndegree(G,indegree);
seqStack s;
InitStack(&s);
for(i = 0;i<G->vexnum;i++)
{
//入度为0的顶点入栈
if(indegree[i]==0){
Push(&s,i);
}
}
count =0;
while(!IsEmpty(&s)){
Pop(&s,&i);
printf("%d ",i);
++count;
int x;
for(x = 0;x<G->vexnum;x++){
k = G->arcs[i][x];
if(k==1){
if((--indegree[x]==0)){
Push(&s,x);
}
}/*if*/
}/*for*/
}/**/
/*回路异常*/
if(count<G->vexnum){
exit(0);
}
}
怎么创建一个邻接矩阵呢,我们在之前的博文里面已写过了一个邻接矩阵的创建函数这里就不多阐述。
下面是所有的代码,包括栈操作,main函数,创建邻接矩阵函数。
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 30
#define Max_Vetex_Num 100
typedef struct {
int vexs[Max_Vetex_Num];
int arcs[Max_Vetex_Num][Max_Vetex_Num];
int vexnum,arcnum;
}Mgraph;
typedef struct{
int *base;
int *top; //栈顶指针
int size;
}seqStack;
int InitStack(seqStack *s){
s->base = (int *)malloc(STACK_SIZE* sizeof(seqStack));//动态分配30个单位的stack
//省略是否空间满
s->top = s->base;//栈顶和栈尾相同,栈里面没有元素
s->size = STACK_SIZE;
return 1;
}
int Push(seqStack *s,int x){
*s->top = x;
s->top++;
return 1;
}
int Pop(seqStack *s,int *x){
if(s->top == s->base)return 0;
else{
s->top--;
*x = *s->top;
return 1;
}
}
int IsEmpty(seqStack *s){
if(s->top==s->base){
return 1;
}else{
return 0;
}
}
int GetTop(seqStack *s, int *x){
if(s->top==s->base)
return 0;
else{
*x=*(s->top-1);
return 1;
}
}
void FindIndegree(Mgraph *G,int indegree[])
{
int i;
int j;
for(i = 0;i<G->vexnum ;i++)
{
for(j= 0;j<G->vexnum;j++)
{
if(G->arcs[j][i]==1){
indegree[i]++;
}
}
}/*for*/
}/*end*/
void TopSort(Mgraph *G){
int i,j,k;
int count;
int indegree[G->vexnum];
for(i = 0;i<G->vexnum ;i++)
{
indegree[i] = 0;
}
FindIndegree(G,indegree);
seqStack s;
InitStack(&s);
for(i = 0;i<G->vexnum;i++)
{
//入度为0的顶点入栈
if(indegree[i]==0){
Push(&s,i);
}
}
count =0;
while(!IsEmpty(&s)){
Pop(&s,&i);
printf("%d ",i);
++count;
int x;
for(x = 0;x<G->vexnum;x++){
k = G->arcs[i][x];
if(k==1){
if((--indegree[x]==0)){
Push(&s,x);
}
}/*if*/
}/*for*/
}/**/
/*回路异常*/
if(count<G->vexnum){
exit(0);
}
}
void CreateMGraph(Mgraph *G){
int type;
int i,j,k,w;
int v1,v2;
scanf("%d,%d",&(G->vexnum),&(G->arcnum));
//自动构造顶点信息为index
for(i=0;i<G->vexnum;i++)
{
G->vexs[i]=i;
}
//初始化邻接矩阵,全部为0
for(i=0;i<G->vexnum;i++){
for(j=0;j<G->vexnum;j++){
G->arcs[i][j]=0;
}
}
//输入每行一个边的偶对,如v1,v2
for(k=0;k<G->arcnum;k++)
{
scanf("%d,%d",&v1,&v2);
G->arcs[v1][v2]=1;
}
//PrintVex(G);
}
int main()
{
Mgraph G;
CreateMGraph(&G);
//PrintVex(&G);
TopSort(&G);
return 0;
}