拓扑排序蟒蛇 [英] Topological sort python
问题描述
I codeD的DFS非递归的解决方案,但我不能修改它,使拓扑排序:
高清DFS(图,开始):
路径= []
堆栈= [开始]
而堆栈= []!
V = stack.pop()
如果v不是路径:path.append(五)
为瓦特在逆转(图[V]):
当w不在路径,而不是中W堆栈:
stack.append(w)的
返回路径
任何想法如何修改?
使用递归的版本,我可以轻松拥有排序:
高清dfs_rec(图,启动,路):
路径=路径+ [开始]
在图形边缘[开始]:
如果不是在道路边:
PATH = dfs_rec(图,边,路径)
打印开始
返回路径
输入:
>>>图= {
1:[2,3]
2:[4,5,6]中
3:[4,6],
4:[5,6],
5:[6],
6:[]
}
>>> dfs_rec(曲线图中,1,[])
6
五
4
2
3
1
[1,2,4,5,6,3]
>>> DFS(图中,1)
[1,2,4,5,6,3]
>>>图= {
1:[3],
3:[5,6],
5:[4],
4:[7],
7:[],
6:[]
}
>>>打印dfs_rec(图1,[])
7
4
五
6
3
1
[1,3,5,4,7,6]
>>>打印DFS(图1)
[1,3,5,4,7,6]
所以我需要得到这个排序的非递归也。
非递归解决方案:
我认为,这也可能是解决方案,标志着我,如果我错了。
高清DFS(图,开始):
路径= []
堆栈= [开始]
标签的len =(图形)
结果= {}
而堆栈= []!
#这个循环可以其它方式进行也
在堆栈中的元素:
如果元素不是结果:
结果[元] =标签
标签=标签 - 1
V = stack.pop()
如果v不是路径:path.append(五)
为瓦特在逆转(图[V]):
当w不在路径,而不是中W堆栈:
stack.append(w)的
结果= {V:K代表K,V在result.items()}
返回路径,导致
输入:
的图表= {1:[3],3:[5,6],5:[4],4:[7],7:[],6:[] }
打印DFS(图1)
输出:
的([1,3,5,4,7,6],{1:7,2:4,3:5,4:6,5:3,6: 1})
1
/
3
/ \
5 6
/
4
/
7
您似乎递归的解决方案并没有被生产拓扑排序输出。
例如使用该输入:
图= {
1:[2,11],
2:[3],
11:[12],
12:[13]
}
1
/ \
/ 11
/ \
2月12日
/ \
3 13
我们应该得到 13
之前 2
。
但你的递归code的输出是:
3
2
13
12
11
1
与 13
下面 2
。
尽管它应该是:
3
13
2
12
11
1
另外,变量路径
似乎只是探索节点,必须与路径无关(因此应当设置
,没有下令列表
,要进行查找更有效)。
这一切都使得它很难把握你的code和纠正非递归版本,给出的递归没有做它应该。
我刚刚制作的递归解决方案,这使得拓扑排序。它遍历所有的图与深度优先搜索,并保持与相关的层次遍历的节点的词典作为值:
从收藏导入defaultdict
从itertools进口takewhile,算
高清sort_topologically(图表):
levels_by_name = {}
names_by_level = defaultdict(套)
高清walk_depth_first(名):
如果名levels_by_name:
回报levels_by_name [名]
儿童= graph.get(名称,无)
级别= 0,如果没有其他的孩子(1 + MAX(walk_depth_first(L-NAME)的LNAME儿童))
levels_by_name [名] =级别
names_by_level [等级]。新增(名称)
回报水平
在图名称:
walk_depth_first(名)
返回表(takewhile(拉姆达X:X是不是无,(names_by_level.get(ⅰ,无)为i的计数())))
图= {
1:[2,3]
2:[4,5,6]中
3:[4,6],
4:[5,6],
5:[6],
6:[]
}
打印(sort_topologically(图))
下面是一个无堆栈版本。我还没有调试它彻底,但它似乎是工作。
从收藏导入defaultdict
从itertools进口takewhile,算
高清sort_topologically_stackless(图表):
levels_by_name = {}
names_by_level = defaultdict(套)
高清add_level_to_name(名称,等级):
levels_by_name [名] =级别
names_by_level [等级]。新增(名称)
高清walk_depth_first(名):
堆栈= [名]
而(栈):
NAME = stack.pop()
如果名levels_by_name:
继续
如果名称不图形或不绘制[名]:
级别= 0
add_level_to_name(名称,等级)
继续
孩子=图[名]
children_not_calculated = [孩子的孩子的孩子,如果孩子不levels_by_name]
如果children_not_calculated:
stack.append(名)
stack.extend(children_not_calculated)
继续
级别= 1 + MAX(levels_by_name [L-NAME]为LNAME儿童)
add_level_to_name(名称,等级)
在图名称:
walk_depth_first(名)
返回表(takewhile(拉姆达X:X是不是无,(names_by_level.get(ⅰ,无)为i的计数())))
图= {
1:[2,3]
2:[4,5,6]中
3:[4,6],
4:[5,6],
5:[6],
6:[]
}
打印(sort_topologically_stackless(图))
I coded a solution for DFS non-recursive, but i can't modify it to make a topological sort:
def dfs(graph,start):
path = []
stack = [start]
while stack != []:
v = stack.pop()
if v not in path: path.append(v)
for w in reversed(graph[v]):
if w not in path and not w in stack:
stack.append(w)
return path
Any ideas how to modify it?
With the recursive version i can easy have the sorting:
def dfs_rec(graph,start,path):
path = path + [start]
for edge in graph[start]:
if edge not in path:
path = dfs_rec(graph, edge,path)
print start
return path
Input:
>>> graph = {
1: [2, 3],
2: [4, 5, 6],
3: [4,6],
4: [5,6],
5: [6],
6: []
}
>>> dfs_rec(graph,1,[])
6
5
4
2
3
1
[1, 2, 4, 5, 6, 3]
>>> dfs(graph,1)
[1, 2, 4, 5, 6, 3]
>>> graph = {
1: [3],
3: [5,6],
5: [4],
4: [7],
7: [],
6: []
}
>>> print dfs_rec(graph,1,[])
7
4
5
6
3
1
[1, 3, 5, 4, 7, 6]
>>> print dfs(graph,1)
[1, 3, 5, 4, 7, 6]
so i need to get this ordering in the non-recursive also.
Non-recursive solution:
I think that this also could be the solution, mark me if i am wrong.
def dfs(graph,start):
path = []
stack = [start]
label = len(graph)
result = {}
while stack != []:
#this for loop could be done in other ways also
for element in stack:
if element not in result:
result[element] = label
label = label - 1
v = stack.pop()
if v not in path: path.append(v)
for w in reversed(graph[v]):
if w not in path and not w in stack:
stack.append(w)
result = {v:k for k, v in result.items()}
return path,result
Input:
graph = { 1: [3], 3:[5,6] , 5:[4] , 4:[7], 7:[],6:[]}
print dfs(graph,1)
Output:
([1, 3, 5, 4, 7, 6], {1: 7, 2: 4, 3: 5, 4: 6, 5: 3, 6: 1})
1
/
3
/\
5 6
/
4
/
7
You recursive solution doesn't seem to be producing topologically sorted output.
For example with this input:
graph = {
1: [2,11],
2: [3],
11: [12],
12: [13]
}
1
/\
/ 11
/ \
2 12
/ \
3 13
we should get 13
prior to 2
.
But the output of your recursive code is:
3
2
13
12
11
1
with 13
following2
.
While it should be:
3
13
2
12
11
1
Furthermore, the variable path
seems to be just explored nodes and has nothing to do with path (and thus it should be set
, not ordered list
, to be more efficient for lookups).
All this makes it very difficult to grasp your code and correct the non-recursive version, given the recursive doesn't do what it should.
I've just crafted a recursive solution which makes a topological sorting. It traverses all the graph with depth-first-search and keeps a dictionary of traversed nodes with associated levels as values:
from collections import defaultdict
from itertools import takewhile, count
def sort_topologically(graph):
levels_by_name = {}
names_by_level = defaultdict(set)
def walk_depth_first(name):
if name in levels_by_name:
return levels_by_name[name]
children = graph.get(name, None)
level = 0 if not children else (1 + max(walk_depth_first(lname) for lname in children))
levels_by_name[name] = level
names_by_level[level].add(name)
return level
for name in graph:
walk_depth_first(name)
return list(takewhile(lambda x: x is not None, (names_by_level.get(i, None) for i in count())))
graph = {
1: [2, 3],
2: [4, 5, 6],
3: [4,6],
4: [5,6],
5: [6],
6: []
}
print(sort_topologically(graph))
Here is a stackless version. I haven't debugged it thoroughly, but it seems to be working.
from collections import defaultdict
from itertools import takewhile, count
def sort_topologically_stackless(graph):
levels_by_name = {}
names_by_level = defaultdict(set)
def add_level_to_name(name, level):
levels_by_name[name] = level
names_by_level[level].add(name)
def walk_depth_first(name):
stack = [name]
while(stack):
name = stack.pop()
if name in levels_by_name:
continue
if name not in graph or not graph[name]:
level = 0
add_level_to_name(name, level)
continue
children = graph[name]
children_not_calculated = [child for child in children if child not in levels_by_name]
if children_not_calculated:
stack.append(name)
stack.extend(children_not_calculated)
continue
level = 1 + max(levels_by_name[lname] for lname in children)
add_level_to_name(name, level)
for name in graph:
walk_depth_first(name)
return list(takewhile(lambda x: x is not None, (names_by_level.get(i, None) for i in count())))
graph = {
1: [2, 3],
2: [4, 5, 6],
3: [4,6],
4: [5,6],
5: [6],
6: []
}
print(sort_topologically_stackless(graph))
这篇关于拓扑排序蟒蛇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!