【数据结构】【图文】【oj习题】 图的拓扑排序(邻接表)

拓扑排序:
按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系,由此所得顶点的线性序列称之为拓扑有序序列。显然对于有回路的有向图得不到拓扑有序序列,因为有回路的话,顶点的先后次序就不确定了。
例如:例如,下图,我们可以人为限定次序:A B C D 或 A C B D

解释:该输出顺序特点就是后面的顶点输出必然后于该顶点的前驱顶点
算法:
- 从有向图中选取一个没有前驱(没有在它之前活动)的顶点,输出之;
- 从有向图中删去此顶点以及所有以它为尾的弧;
- 重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
- 没有被打印输出的顶点构成回路了。
那么、如何找到一个没有前驱的顶点呢?
通过解释看出,没有前驱的顶点的入度为零。我们每次重复第一个操作就是找到图中入度为零的点并且输出。
当然问题来了,如果图中有多个入度为零的顶点,如何判断谁先输出。或者怎么依次输出它们?
答:这里可以利用栈(队列),暂时将其入栈(入队),每次输出栈顶(队头)元素。因为每次都是输出的入度为零的节点,不同的存储方式可能造成输出顺序的不同,但是他们都遵循拓扑排序。都是拓扑排序的一种情况。

注意:
- ingress[]:用来存每个顶点的入度
- 图的存储结构:邻接表(不懂可以看我的上一篇随笔)
获取各顶点入度的函数:
void FindID(AdjList G, int indegree[MAX_VERTEX_NUM]){
int i;
ArcNode *p;
for(i=0;i<G.vexnum;i++) /*--初始化度数组----*/
indegree[i]=0;
for(i=0;i<G.vexnum;i++){
p=G.vertexes[i].firstarc; //找邻接点
while(p!=NULL){
indegree[p->adjvex]++;
p=p->nextarc;
}
}
}
入栈方法输出拓扑排序
bool TopologicalSort(ALGraph G)
{
SeqStack *s;
s = (SeqStack*)malloc(sizeof(SeqStack));
InitStack(s); /*---初始化栈---*/
int count,indegree[G.vexnum]; /*--count:用来计数---*/
ArcNode *p;
FindIndegree(G, indegree); /*---获取各顶点入度的函数---*/
int j;
for(j = 0;j<G.vexnum;j++)
{
if(indegree[j]==0)
push(s,j); /*--找到一个度为零的入栈----*/
}
count = 0;
while(!IsEmpty(s)) /*---栈非空---*/
{
int i = 0;
Pop(s,&i); /*---度为零的出栈并输出---*/
printf("%d ",i);
count++;
for( p = G.adjlist[i].firstarc;p;p = p->nextarc)
{ /*---将出栈的顶点尾部的弧’删除‘(其实是将所尾部连接的顶点的度减一)---*/
indegree[p->adjvex]--;
if(!indegree[p->adjvex]) push(s,p->adjvex);
}
}
if(count == G.vexnum) /*---出栈顶点数目等于图的顶点数说明图中无回路,否则有回路---*/
{
return true;
}
return false;
}
入对方法输出拓扑排序
int TopoSort(AdjList G){
Queue Q; /*队列存储入度为0*/
int indegree[MAX_VERTEX_NUM]; //存放每个顶点的入度值
int i,count,k; //count计数,然后和有向图中顶点总数比较
ArcNode*p;
FindID(G,indegree);
InitStack(&S); //初始化队列
for(i=0;i<G.vexnum;i++)
if(indegree[i]==0) EnterQueue(&Q,i); //入队
count=0;
while(!StackEmpty(S)){
DeleteQueue(&Q,&i); //一个入度为0的点出队
printf("%c",G.vertex[i].data);
count++;
p=G.vertexes[i].firstarc;
while(p!=NULL){
k=p->adjvex;
indegree[k]--;
if(indegree[k]==0) EnterQueue(&S,k);
p=p->nextarc;
}
}
if(count<G.vexnum) return(Error); //有向图中有回路
else return(Ok);
}
时间复杂度
如果AOV网络有n个顶点,e条边,在拓扑排序的过程中,搜索入度为零的顶点所需的时间是O(n)。在正常情况下,每个顶点进一次栈,出一次栈,所需时间O(n)。每个顶点入度减1的运算共执行了e次。所以总的时间复杂为O(n+e)。
oj题目要求:(入栈)拓扑排序
【数据结构】【图文】【oj习题】 图的拓扑排序(邻接表)的更多相关文章
- hdu 2647 (拓扑排序 邻接表建图的模板) Reward
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2647 老板给员工发工资,每个人的基本工资都是888,然后还有奖金,然后员工之间有矛盾,有的员工希望比某员 ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- C#实现有向无环图(DAG)拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在 ...
- Paint the Grid Again (隐藏建图+优先队列+拓扑排序)
Leo has a grid with N × N cells. He wants to paint each cell with a specific color (either black or ...
- 图的拓扑排序,AOV,完整实现,C++描述
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)
题意: 策策同学特别喜欢逛公园. 公园可以看成一张 N 个点 M 条边构成的有向图,且没有自环和重边.其中 1 号点是公园的入口, N 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花 ...
- 算法87-----DAG有向无环图的拓扑排序
一.题目:课程排表---210 课程表上有一些课,是必须有修学分的先后顺序的,必须要求在上完某些课的情况下才能上下一门.问是否有方案修完所有的课程?如果有的话请返回其中一个符合要求的路径,否则返回[] ...
- 18.boost 图的拓扑排序
运行结果: 代码示例: #include <iostream> #include <vector> #include <deque> #include <bo ...
- POJ - 3249 Test for Job (在DAG图利用拓扑排序中求最长路)
(点击此处查看原题) 题意 给出一个有n个结点,m条边的DAG图,每个点都有权值,每条路径(注意不是边)的权值为其经过的结点的权值之和,每条路径总是从入度为0的点开始,直至出度为0的点,问所有路径中权 ...
随机推荐
- dp凸优化/wqs二分学习笔记(洛谷4383 [八省联考2018]林克卡特树lct)
qwq 安利一个凸优化讲的比较好的博客 https://www.cnblogs.com/Gloid/p/9433783.html 但是他的暴力部分略微有点问题 qwq 我还是详细的讲一下这个题+这个知 ...
- ReentrantLock可重入锁、公平锁非公平锁区别与实现原理
ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...
- FastAPI 学习之路(十八)表单与文件
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...
- RabbitMQ延时队列应用场景
应用场景 我们系统未付款的订单,超过一定时间后,需要系统自动取消订单并释放占有物品 常用的方案 就是利用Spring schedule定时任务,轮询检查数据库 但是会消耗系统内存,增加了数据库的压力. ...
- Less-23 preg_replace1
Less-23: 直接跳到Less-23的原因是,Less-(11~22)均为注入点不为get方式的注入.我先把get型注入写的差不多,再回来整理关于注入点的内容. 核心语句: 查询.报错均有回显. ...
- 【UE4 C++ 基础知识】<12> 多线程——FRunnable
概述 UE4里,提供的多线程的方法: 继承 FRunnable 接口创建单个线程 创建 AsyncTask 调用线程池里面空闲的线程 通过 TaskGraph 系统来异步完成一些自定义任务 支持原生的 ...
- Ruby on Rails 单元测试
Ruby on Rails 单元测试 为什么要写测试文件? 软件开发中,一个重要的环节就是编写测试文件,对代码进行单元测试,确保程序各部分功能执行正确.但是,这一环节很容易被我们轻视,认为进行单元测试 ...
- mysql的一些配置操作
mysql的一些配置操作 一.背景 二.mysql配置 三.慢查询日志 1.命令行临时生效 2.配置文件修改永久生效 3.慢查询日志解释 4.mysqldumpdlow查看慢查询日志 四.查看索引为何 ...
- 关于麦克风的参数介绍 - 驻极体麦克风(ECM)和硅麦(MEMS)
1.麦克风的分类1.1.动圈式麦克风(Dynamic Micphone)原理:基本构造包含线圈.振膜.永久磁铁三部分.当声波进入麦克风,振膜受到声波的压力而产生振动,与振膜在一起的线圈则开始在磁场中移 ...
- 攻防世界 web3.backup
如果网站存在备份文件,常见的备份文件后缀名有:.git ..svn..swp..~..bak..bash_history..bkf尝试在URL后面,依次输入常见的文件备份扩展名. ip/index.p ...