我想出了这个简单的算法,因为我在Google上发现的并不那么有用(我只会发现自己并行运行的算法来计算正常的拓扑排序).
visit(node) { maxdist = 0; foreach (e : in_edge(node)) { maxdist = max(maxdist,1 + visit(source(e))) } distance[node] = maxdist; return distance[node]; } make_partial_ordering(node) { set all node distances to +infinite; num_levels = visit(node,0); return sort(nodes,by increasing distance) where distances < +infinite; }
(请注意,这只是伪代码,肯定会有一些可能的小优化)
对于正确性,似乎很明显:对于叶子(= =没有进一步依赖的节点),最大距离到叶始终为0(正确,因为循环由于0边缘而被跳过).
对于连接到节点n1,…,nk的任何节点,最大距离到叶是1 max {distance [n1],..,distance [nk]}.
我写下了算法之后,我找到了这篇文章:http://msdn.microsoft.com/en-us/magazine/dd569760.aspx
但是老实说,他们为什么要做所有的列表复制等等,这似乎真的没有效率?
无论如何,我想知道我的算法是否正确,如果是这样的话,我可以读取一些关于它的东西.
更新:我在我的程序中实现了这个算法,似乎对我测试的一切都很有用.
代码如下:
typedef boost::graph_traits<my_graph> my_graph_traits; typedef my_graph_traits::vertices_size_type vertices_size_type; typedef my_graph_traits::vertex_descriptor vertex; typedef my_graph_traits::edge_descriptor edge; vertices_size_type find_partial_ordering(vertex v,std::map<vertices_size_type,std::set<vertex> >& distance_map) { vertices_size_type d = 0; BOOST_FOREACH(edge e,in_edges(v)) { d = std::max(d,1 + find_partial_ordering(source(e),distance_map)); } distance_map[d].insert(v); return d; }
您可以通过memoizing的find_partial_ordering结果修复此问题,并在您已经计算了特定节点的值时返回而不进行递归.然而,这仍然给你一个堆栈破坏的递归解决方案.
这不符合你的需要吗?
编辑:啊,我明白,你想知道深度边界在哪里,这样你可以在给定的深度平行一切.您仍然可以使用维基百科的算法(因此避免递归).
首先,使用维基百科上的算法进行拓扑排序.现在通过以拓扑顺序访问节点来计算深度:
depths : array 1..n for i in 1..n depths[i] = 0 for j in children of i depths[i] = max(depths[i],depths[j] + 1) return depths
请注意,上面没有递归,只是一个简单的O(| V | | E |)算法.这与维基百科的算法具有相同的复杂性.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。