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));//自动构造顶点信息为indexfor(i=0;i<G->vexnum;i++){G->vexs[i]=i;}//初始化邻接矩阵,全部为0for(i=0;i<G->vexnum;i++){for(j=0;j<G->vexnum;j++){G->arcs[i][j]=0;}}//输入每行一个边的偶对,如v1,v2for(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;
}

C语言利用图的邻接矩阵的存储方式实现拓扑排序相关推荐

  1. 图的两种存储方式---邻接矩阵和邻接表

    图:图是一种数据结构,由顶点的有穷非空集合和顶点之间边的集合组成,表示为G(V,E),V表示为顶点的集 合,E表示为边的集合. 首先肯定是要对图进行存储,然后进行一系列的操作,下面对图的两种存储方式邻 ...

  2. 邻接矩阵的存储方式实现图的广度和深度优先遍历

    在做图的邻接矩阵之前,先做好准备工作,定义存储类型,声明队列的操作(在广度优先遍历中使用) #include <stdio.h> #include <stdlib.h> #in ...

  3. 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径

    文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...

  4. c语言中变量有几种存储方式,C语言变量的存储类别有哪些详细资料介绍

    描述 C语言中的变量根据其生存周期,可以分为静态存储方式和动态存储方式. 静态存储方式:是指在程序运行期间分配固定的存储空间的方式.静态存储区中存放了在整个程序执行过程中都存在的变量,如全局变量. 动 ...

  5. [LeetCode] 局部图论问题探讨-图成环、图度、关键路径、拓扑排序等问题

    写在前面 前面的笔记集分别探讨了图的遍历.图的最小路径和最小生成树问题,本笔记将着重探讨图中其他典型问题,比如图是否成环.图的度使用(无向图).图的入度和出度使用(有向图).图的关键路径和拓扑序问题, ...

  6. C语言 数据结构 图的邻接矩阵存储 基本操作(附输入样例和讲解)

    代码参照了严蔚敏.吴伟民编写的数据结构(C语言版). 部分内容参考了这位大佬: https://blog.csdn.net/jeffleo/article/details/53326648 所有代码采 ...

  7. c语言邻接表的构建_c语言数据结构--图的邻接矩阵和邻接表操作的基本操作

    #include #include #include #define MAX 100 typedef char DataType; typedef int VectorRelationType; ty ...

  8. aov建立Java模拟,数据结构之---C语言实现拓扑排序AOV图

    //有向图的拓扑排序 //杨鑫 #include #include #include #define MAX_NAME 3 #define MAX_VERTEX_NUM 20 typedef int ...

  9. 拓扑排序(完整案列及C语言完整代码实现)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

最新文章

  1. GridView自定义分页导航
  2. springboot filter and interceptor实战之mdc日志打印
  3. 初中英语八下单词表(SuperMemo QA文本格式)
  4. android n等分 layout,RecyclerView GridLayoutManager 等分间距
  5. territory pop up window是否显示的逻辑,和transaction type差不多
  6. Vue-cli(四) 项目中引入Axios
  7. IT民工系列——通用7130芯片视频采集卡 SDK 兼容任意天敏 宏视 等板卡
  8. 微软账号被暂时停用咋办_游戏账号交易要注意什么?买游戏账号有哪些可能会被找回去...
  9. phpcms v9 index.php,Phpcms V9后台登录地址修改方法
  10. SpringMVC文件上传(三)异常栈处理
  11. WPS表格如何在数字前面批量增加人民币符号和在后面添加元?
  12. esxi添加硬盘驱动
  13. python requests 登录接口场景使用案例
  14. 嵌入式Linux--U-Boot(四)MMC命令使用
  15. 使用Matlab将抖音视频转换成gif图片
  16. linux下写脚本时-gt或-lt是什么意思?
  17. OpenGL实现碰撞检测与模拟重力效果(简单的物理系统)
  18. python读取身份证中的生日信息
  19. Kali linux无线网络渗透详解笔记
  20. win10任务栏透明_Win10原生实现全透明任务栏

热门文章

  1. 【LeetCode】513. Find Bottom Left Tree Value
  2. 罗切斯特大学排名计算机排名,2020年罗切斯特大学QS世界排名
  3. 28BYJ-48 电机驱动(Linux)
  4. 2023年东南大学英语笔译考研上岸前辈备考经验指导
  5. Android5.1--PowerManagerService电源管理
  6. 总是在崩溃的边缘徘徊,可能这就是成年人的生活吧!!!!
  7. 高等数学:一元函数微分学
  8. Nestjs中的守卫
  9. 状态机(FSM)的分类描述
  10. 休眠后电脑马上自动唤醒解决