【算法设计与数据结构】拓扑排序算法的实现——Kahn算法及基于dfs的算法
来源:互联网 发布:淘宝质量问题的定义 编辑:程序博客网 时间:2024/04/29 12:35
拓扑排序的定义和原理等我不再赘述,各种教材和网络上都有详细解释,今天我主要谈一谈两种实现拓扑排序的算法。
Kahn算法:
<span style="white-space:pre"></span>将所有入度为0的顶点加入队列q;while(!q.empty() ){u = q.front();q.pop();list.push(u);for (u的每个邻接点v){删除边(u, v);if (indegree(v) == 0)q.push(v);}}if (图G还有边存在)return 存在环elsereturn list;以上这种是比较典型的求拓扑排序的算法,算法复杂度为O(v+e),常可用来判断该图是否是DAG(有向无环图)
在算法导论上,介绍的则是另外一种算法,它是基于DFS的,实现十分简单,仅需要在DFS中多加一个语句即可。
基于DFS的拓扑排序算法(前提:图是DAG):
L ← 用于存放排序结果的数组S ← 出度为0的顶点的集合for (S中的每个顶点) dfs(n) void dfs(node n){if (!vis[n]){vis[n] = true;for (每一个顶点m,满足m->n)dfs(m);} L.push(n);}
可以看到,我们只是在dfs函数快退出时将结点加入到L中而已。
(注意,for中的顶点m,满足的是m->n而不是n->m)
下面简单证明一下它的正确性:
对任意的边m->n,当调用dfs(n)的时候,有如下两种情况:
1) dfs(m)还没有被调用,此时会调用dfs(m),只有dfs(m)返回之后,dfs(n)才会返回
2) dfs(m)已经被调用过并返回了
(由于本图是DAG,所以不存在dfs(m)已经被调用,但是在dfs(n)在被调用时还未返回的情况)
无论是以上哪一种情况,m都会先于n被添加到L中。所以对于任意边m->n,在L中,m总会在n前面。
本算法的复杂度为O(v+e),需要注意的一些点是,本算法是建立在图为DAG的基础上的,当然,可以进行一些修改来做环路检测,另外, 本算法的起点是对每个出度为0的顶点进行dfs,而Kahn算法则是从每个入度为0的顶点出发。为何本算法需要从出度为0的顶点出发呢?因为出度为0的顶点必然排在最后面,而最先调用dfs的顶点最后才加入L中。
对比两种算法,有着异曲同工之妙,一个从入度为0的顶点出发,一个从出度为0的顶点出发;一个对m->n中的每个n进行操作,一个对m->n中的每个m进行操作。
如果需要判断该图是否为DAG,那么第一种算法是不错的选择,如果已经知道该图为DAG,则第二种算法更加简洁!
0 0
- 【算法设计与数据结构】拓扑排序算法的实现——Kahn算法及基于dfs的算法
- 拓扑排序的两种实现:Kahn算法和dfs算法
- Kahn算法-拓扑排序
- 拓扑排序:Kahn算法
- 拓扑排序-Kahn算法
- 拓扑排序(Kahn算法和基于DFS求解法)
- HDU-1258(拓扑排序Kahn算法)
- 数据结构与算法——有向无环图的拓扑排序C++实现
- 拓扑排序的算法实现
- 算法与数据结构--拓扑排序
- 【数据结构与算法】拓扑排序
- Kahn算法
- 图基本算法 拓扑排序(基于邻接表的dfs实现)
- hdu1285确定比赛名次(拓扑排序kahn算法)
- 算法:图的拓扑排序-数据结构(23)
- 【数据结构】拓扑排序算法
- 数据结构--拓扑排序算法
- 算法导论--BFS、DFS及拓扑排序
- LeetCode之Power of Two
- Linux内核中断处理的irq_thread机制
- 梁启超写给梁思成及儿女的信
- C++命名空间
- Jedis(redis的Java客户端开发包)
- 【算法设计与数据结构】拓扑排序算法的实现——Kahn算法及基于dfs的算法
- POJ 3276 Face The Right Way(开关问题)
- 【LeetCode】之Remove Duplicates from Sorted Array II
- Linux之进程控制
- 标识接口的作用
- 月老的难题
- HDU 5115 Dire Wolf(2014ACM/ICPC北京赛区现场赛D)
- HDU——2101 A + B Problem Too
- http和www