如何无需Shell输出生成器对象?求完善DFS图环查找函数
嘿,我来帮你解决这两个技术问题~
1. 不使用生成器(Generator)返回结果的方法
生成器最大的特点就是“懒”——它不会一下子算出所有结果,而是用到的时候才产出值。如果你不想用生成器,最直接的替代方式就是用列表来收集所有符合条件的结果:每次找到目标路径,就把它添加到列表里,最后直接返回这个列表就行。
比如把你原生成器版本的代码改成非生成器版本:
def dfs(graph, start, end): result = [] # 用列表存所有找到的路径 fringe = [(start, [])] while fringe: state, path = fringe.pop() if path and state == end: result.append(path) # 找到路径就塞到列表里 continue for next_state in graph[state]: if next_state not in path: fringe.append((next_state, path + [state])) return result
调用的时候直接拿到结果列表,不用再通过shell去迭代生成器:
# 举个测试用的图 graph = { 'A': ['B', 'C'], 'B': ['A', 'D'], 'C': ['A'], 'D': ['B'] } paths = dfs(graph, 'A', 'A') print(paths) # 直接打印就能看到所有路径啦
2. 整合DFS找环的逻辑(无需生成器)
首先咱们得明确:图里的环是指从某个节点出发,绕一圈又回到它自己,而且路径长度至少是2(不然单个节点自己也算环了,这一般不是咱们要的)。你的原代码是找从start到end的路径,咱们调整下逻辑,把找环的逻辑整合进去,用列表收集所有环,还要注意避免重复的环(比如A->B->A和B->A->B其实是同一个环,咱们可以只保留以环里字典序最小的节点为起点的环,来避免重复)。
给你一个完整的非生成器版本找环函数:
def find_all_cycles(graph): all_cycles = [] visited = set() # 记录已经处理过的节点,避免重复查同一个节点的环 def dfs_cycle(node, path): if node in path: # 找到环的起始位置,把环的部分截出来 cycle_start_idx = path.index(node) cycle = path[cycle_start_idx:] + [node] # 去重:只留环里最小节点当起点的环,避免重复记录同一个环 if cycle[0] == min(cycle): all_cycles.append(cycle) return if node in visited: return visited.add(node) for neighbor in graph[node]: dfs_cycle(neighbor, path + [node]) # 遍历每个节点,找所有可能的环 for node in graph: dfs_cycle(node, []) return all_cycles
调用示例:
graph = { 'A': ['B', 'C'], 'B': ['A', 'D'], 'C': ['A'], 'D': ['B', 'E'], 'E': ['D'] } cycles = find_all_cycles(graph) print(cycles) # 输出会是:[['A', 'B', 'A'], ['B', 'D', 'E', 'D']]
顺便说下生成器的显示问题
你说不清楚怎么显示生成器的结果,其实核心就是生成器是惰性迭代器——它不会主动把所有结果都算好存在那里,只有当你去迭代它的时候,才会逐个产出值。比如原生成器版本的函数,你可以用这两种方式拿到结果:
# 方法1:把生成器转成列表 generator_obj = dfs(graph, 'A', 'A') print(list(generator_obj)) # 方法2:用for循环遍历生成器 for path in dfs(graph, 'A', 'A'): print(path)
这样就能看到生成器里的所有路径啦~
内容的提问来源于stack exchange,提问作者Oscar Dolloway
相关产品推荐
相关产品推荐

