写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留有遗憾的事,做自己觉得有意义的事,不浪费这大好的青春年华。博主写博客目的是记录所学到的知识并方便自己复习,在记录知识的同时获得部分浏览量,得到更多人的认可,满足小小的成就感,同时在写博客的途中结交更多志同道合的朋友,让自己在技术的路上并不孤单。

目录:
1.全序和偏序
2.拓扑排序的方法
3.拓扑排序C语言完整代码实现
4.拓扑排序小结

1.全序和偏序

拓扑排序指的是将有向无环图(又称“DAG”图)中的顶点按照图中指定的先后顺序进行排序。

例如,上图 中的两个图都是有向无环图,都可以使用拓扑排序对图中的顶点进行排序,两个图形的区别是:左图中的 V2 和 V3之间没有明确的前后顺序;而右图中任意两个顶点之间都有前后顺序。

所以,左图中顶点之间的关系被称为“偏序”关系;右图中顶点之间的关系被称为”全序“关系。全序是偏序的一种特殊情况。对于任意一个有向无环图来说,通过拓扑排序得到的序列首先一定是偏序,如果任意两个顶点都具有前后顺序,那么此序列是全序。

2.拓扑排序的方法

对有向无环图进行拓扑排序,只需要遵循两个原则:

  1. 在图中选择一个没有前驱的顶点 V;
  2. 从图中删除顶点 V 和所有以该顶点为尾的弧

上面左图拓扑排序如下:

对于此图来说,拓扑排序有两种:

1.V1 -> V2 -> V3 -> V4
2.V1 -> V3 -> V2 -> V4
如果顶点之间只是具有偏序关系,那么拓扑排序的结果肯定不唯一;如果顶点之间是全序关系,那么拓扑排序得到的序列唯一

有向无环图如果顶点本身具有某种实际意义,例如用有向无环图表示大学期间所学习的全部课程,每个顶点都表示一门课程,有向边表示课程学习的先后次序,例如要先学《程序设计基础》和《离散数学》,然后才能学习《数据结构》。所以用来表示某种活动间的优先关系的有向图简称为“AOV 网”。

3.拓扑排序C语言完整代码实现

在编写程序解决拓扑排序的问题时,大致思路为:首先通过邻接表将 AOV 网进行存储,由于拓扑排序的整个过程中,都是以顶 点的入度为依据进行排序,所以需要根据建立的邻接表统计出各顶点的入度。 在得到各顶点的入度后,首先找到入度为 0 的顶点作为拓扑排序的起始点,然后查找以该顶点为起始点的所有顶点,如果入度 为 1,说明如果删除前一个顶点后,该顶点的入度为 0,为拓扑排序的下一个对象

#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 20//最大顶点个数
#define VertexType int//顶点数据的类型
typedef enum{false,true} bool;
typedef struct ArcNode{int adjvex;//邻接点在数组中的位置下标struct ArcNode * nextarc;//指向下一个邻接点的指针
}ArcNode;
typedef struct VNode{VertexType data;//顶点的数据域ArcNode * firstarc;//指向邻接点的指针
}VNode,AdjList[MAX_VERTEX_NUM];//存储各链表头结点的数组
typedef struct {AdjList vertices;//图中顶点及各邻接点数组int vexnum,arcnum;//记录图中顶点数和边或弧数
}ALGraph;
//找到顶点对应在邻接表数组中的位置下标
int LocateVex(ALGraph G,VertexType u){for (int i=0; i<G.vexnum; i++) {if (G.vertices[i].data==u) {return i;}}return -1;
}
//创建 AOV 网,构建邻接表
void CreateAOV(ALGraph **G){*G=(ALGraph*)malloc(sizeof(ALGraph)); scanf("%d,%d",&((*G)->vexnum),&((*G)->arcnum));for (int i=0; i<(*G)->vexnum; i++) {scanf("%d",&((*G)->vertices[i].data));(*G)->vertices[i].firstarc=NULL;}VertexType initial,end;for (int i=0; i<(*G)->arcnum; i++) { scanf("%d,%d",&initial,&end);ArcNode *p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=LocateVex(*(*G), end);p->nextarc=NULL;int locate=LocateVex(*(*G), initial);p->nextarc=(*G)->vertices[locate].firstarc;(*G)->vertices[locate].firstarc=p;}
}
//结构体定义栈结构
typedef struct stack{VertexType data; struct stack * next;
}stack;
//初始化栈结构
void initStack(stack* *S){(*S)=(stack*)malloc(sizeof(stack));
(*S)->next=NULL;
}
//判断链表是否为空
bool StackEmpty(stack S){if (S.next==NULL) { return true;}return false;
}
//进栈,以头插法将新结点插入到链表中
void push(stack *S,VertexType u){stack *p=(stack*)malloc(sizeof(stack));p->data=u;p->next=NULL;p->next=S->next;S->next=p;
}
//弹栈函数,删除链表首元结点的同时,释放该空间,并将该结点中的数据域通过地址传值给变量 i; void pop(stack *S,VertexType *i){ stack *p=S->next; *i=p->data;S->next=S->next->next;free(p);
}
//统计各顶点的入度
void FindInDegree(ALGraph G,int indegree[]){//初始化数组,默认初始值全部为 0for (int i=0; i<G.vexnum; i++) {indegree[i]=0;}
//遍历邻接表,根据各链表中结点的数据域存储的各顶点位置下标,在 indegree 数组相应位置+1for (int i=0; i<G.vexnum; i++) {ArcNode *p=G.vertices[i].firstarc; while (p) {indegree[p->adjvex]++;p=p->nextarc;}
}
}
void TopologicalSort(ALGraph G){int indegree[G.vexnum];//创建记录各顶点入度的数组FindInDegree(G,indegree);//统计各顶点的入度
//建立栈结构,程序中使用的是链表stack *S;initStack(&S);
//查找度为 0 的顶点,作为起始点for (int i=0; i<G.vexnum; i++) {if (!indegree[i]) {push(S, i);}}int count=0;
//当栈为空,说明排序完成while (!StackEmpty(*S)) {int index;
//弹栈,并记录栈中保存的顶点所在邻接表数组中的位置pop(S,&index);printf("%d",G.vertices[index].data);++count;
//依次查找跟该顶点相链接的顶点,如果初始入度为 1,当删除前一个顶点后,该顶点入度为 0for (ArcNode *p=G.vertices[index].firstarc; p; p=p->nextarc) {VertexType k=p->adjvex;if (!(--indegree[k])) {//顶点入度为 0,入栈push(S, k);}}}
//如果 count 值小于顶点数量,表明该有向图有环if (count<G.vexnum) {printf("该图有回路"); return;}
}
int main(){ALGraph *G;CreateAOV(&G);//创建 AOV 网TopologicalSort(*G);//进行拓扑排序return 0;
}

对于下面例子

进行拓扑排序:

//输入
6,8
1
2
3
4
5
6
1,2
1,4
1,3
3,2
3,5
4,5
6,4
6,5
//输出
6 1 4 3 2 5

4.拓扑排序小结

对于含有n个顶点和e条边的有向图而言,建立求各个顶点的入度的时间复杂度为O(e);建立0入度顶点栈的时间复杂度为O(n),在拓扑排序中若有向图无环,则每个顶点进一次栈出一次栈,所以总的时间复杂度为O(n+e)

本篇博客转载C语言中文网

拓扑排序(完整案列及C语言完整代码实现)相关推荐

  1. 深入继承之抽象类和接口综合分析及完整案列解说(一)

    首先感谢园里的一位前辈anytao.cnblogs.com ,他对面向抽象类和接口编程作出比较完善的总结.下面的总结是直接Copy他的原话. 一.相同点 ● 都不能被直接实例化,都可以通过继承实现其抽 ...

  2. yp北京理工 拓扑排序+最短路(更新中re)

    contents: 写在前面 拓扑排序 代码 对应题目 AC代码 最短/长路 无权最短路 无权最长路 带权最短路 带权最长路 spfa 优先对列优化dijkstra BELLMAN_FORD FLOY ...

  3. 【拓扑排序】【DP】旅行计划(luogu 1137)

    旅行计划 luogu 1137 题目大意: 有一堆点,之间连接着一些边(有向),保证无环,现在要求出从任意地方出发到所有点的最长路(出发点不一定相同) 原题: 题目描述 小明要去一个国家旅游.这个国家 ...

  4. hdu 4857 逃生 拓扑排序

    逃生 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4857 Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只 ...

  5. 洛谷 P1983 车站分级(拓扑排序)

    https://www.luogu.com.cn/problem/P1983 思路 对于每一趟车,将其经过的车站中,停靠的和不停靠的连一条边,注意边的去重,要双向标记,不然有个点会超时,这样拓扑排序递 ...

  6. C++ 拓扑排序算法

    拓扑排序 有向无环图      如果一个有向图的任意顶点都无法通过一些有向边回到自身,那么称这个有向图为有向无环图. 拓扑排序      拓扑排序是将有向无环图G的所有顶点排成一个线性序列,使得对图G ...

  7. C语言实现拓扑排序topological sort算法(附完整源码)

    C语言实现图拓扑排序算法 node结构体,Graph结构体,Stack结构体 实现以下9个接口 完整头文件 完整源文件 完整main函数测试文件 node结构体,Graph结构体,Stack结构体 s ...

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

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

  9. 【数据结构】有向无环图(AOV-网)的拓扑排序(C语言)

    目录 1. 拓扑序列 2. 拓扑排序的实现(以邻接表为例) 2.1 基本思想 2.2 完整实现代码及运行结果 1. 拓扑序列 有向无环图是指一个无环的有向图.有向无环图可用来描述工程或系统的进行过程, ...

最新文章

  1. Kotlin学习笔记(五) 扩展函数 扩展属性
  2. mysql给root开启远程访问权限,修改root密码
  3. Linux C函数库参考手册
  4. Android应用插件式开发解决方法[转]
  5. 全国计算机等级考试题库二级C操作题100套(第01套)
  6. 迭代反投影法代码_Ceres求解直接法BA实现自动求导
  7. mysql ssl 1067_mysql服务无法启动1067错误,谁知道正确的解决方法?
  8. php 除数 保留两位小数,c语言除法怎么保留小数
  9. 织梦后台登录一直提示验证码不正确
  10. 图片一句话木马简单制作方法
  11. 计算机 host id是指,关于如何修改hostid的问题Windows系统 -电脑资料
  12. Nios II自学笔记一:Nios II软硬件架构介绍
  13. 计算机房的正常温度和湿度,机房的温度、湿度标准值是多少?
  14. 洛谷P3356 火星探险问题(费用流)
  15. Chromium 手势插件
  16. 关于@Result注解的说明
  17. 深圳APP开发红孩儿金融APP
  18. DB2表空间状态代码解释
  19. Templates基础
  20. 达人评测 n5095和i3 10110u选哪个

热门文章

  1. 浅析State-Thread
  2. 【最后一天倒计时】你离¥399网易黑猪肉券就差一步
  3. 微信小程序,图片居中显示,适配不同机型
  4. 腾讯面试后续 | 掘金技术征文
  5. 诺基亚基于区块链推环境感知服务,助力智慧城市发展
  6. Android Demos
  7. 我觉得要技术者上升到整体去考虑会好点
  8. 博客No.1活动暂停公告
  9. 小白2分钟学会Visual Studio将引用包打包到NuGet上
  10. spring boot 整合mongoDb