简体   繁体   English

修改后的深度优先搜索Python

[英]Modified Depth-First-Search Python

I'm looking to do a DFS through a graph to find nodes connected in a specific way. 我正在寻找通过图进行DFS查找以特定方式连接的节点。

graphed = {
    1: [25, 30], 2: [11], 3: [13], 4: [17], 5: [17],
    6: [26], 7: [11, 12], 8: [10, 13], 9: [14, 26],
   10: [8, 11, 15], 11: [2, 7, 10], 12: [7, 16, 17],
   13: [3, 8, 14], 14: [9, 13, 20], 15: [10, 19],
   16: [12, 18], 17: [4, 5, 12], 18: [16, 21, 22],
   19: [15, 28, 29], 20: [14, 25], 21: [18, 23],
   22: [18, 24], 23: [21, 27], 24: [22, 27], 25: [1, 20],
   26: [6, 9], 27: [23, 24], 28: [19], 29: [19], 30: [1]
}

letters = {
    'S': [1],
    'C': [10, [11], [12], [13], [14], [15], [16], [17],
              [18], [19], [20], [21], [22], [23], [24],
              [25], [26], [27], [28], [29], [30] ],
    'O': [2, [3], [4], [5], [6]],
    'N': [7, [8], [9]]}


some_string = 'CO'

def dfs(graph, start, num, visited = None):
    # depth first search for connected nodes
    k = some_string[num]
    y = some_string[(num+1)]
    if visited is None:
        visited = []

    if start in visited:
        return

    visited.append(start)
    # if start corresponds to first letter of string, continue
    if start in letters.get(k):
        # find all nodes that it is connected too
        for each in [x for x in graph[start] if x not in visited]:
            # if any of the connected nodes correspond to
            #   the next letter of string, continue...
            if [each] in letters.get(y):
                dfs(graph, each, (num+1), visited) #recursion

    return visited

lst1 = []
for i in range(1,len(graphed)): 
     lst1.append(dfs(graphed, i, 0))
print(lst1)

Currently, all that is returned by the DFS function is the original start value, for i in range. 当前,DFS函数返回的所有内容都是原始起始值,对于i在范围内。

[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
 [11], [12], [13], [14], [15], [16], [17], [18], [19], [20],
 [21], [22], [23], [24], [25], [26], [27], [28], [29]]

I expect this: 我期望这样:

[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10],
 [11, 2], [12], [13,3], [14], [15], [16], [17,4], [17,5],
 [18], [19], [20], [21], [22], [23], [24], [25], [26,6],
 [27], [28], [29]]

To clarify: I expect the program to run the dfs function; 需要说明的是:我希望程序运行dfs函数; if the start value is a value in 'C', find all nodes connected and check if they're in 'O'; 如果起始值是“ C”中的值,则找到所有连接的节点并检查它们是否在“ O”中; if they are, do the dfs with them; 如果是,请与他们一起进行dfs; if not, return the single value. 如果不是,则返回单个值。

Hopefully this is clear, I can't get my head around why it won't work. 希望这很清楚,我无法理解为什么它不起作用。 Any help is appreciated, thanks. 任何帮助表示赞赏,谢谢。

There are several problems with this code. 此代码存在几个问题。 I recommend that you start over and use incremental programming: write a few lines of code, debug them, and don't continue until they work the way you want. 我建议您重新开始并使用增量编程:编写几行代码,对其进行调试,然后直到它们以所需的方式工作时才继续。 You're not getting some of the functionality your comments seem to assume. 您没有获得您的注释似乎具有的某些功能。

  1. I'm not sure that your list of visited nodes operates as you want. 我不确定您访问过的节点列表是否可以按需运行。 This gets reset every time you return to the for loop in your main program. 每次您返回主程序中的for循环时,都会重置此设置。
  2. Your main program doesn't hit the last node, 30. 您的主程序没有到达最后一个节点30。
  3. I suspect that your main problem is your node notation. 我怀疑您的主要问题是节点符号。 I'm not sure what you intend with a list such as [7, [8], [9]] , where the node numbers are on different levels of nesting, but your logic seems to assume that there is no nesting. 我不确定使用[7,[8],[9]]之类的列表打算做什么,其中的节点号位于不同的嵌套级别,但是您的逻辑似乎假定没有嵌套。 You don't find some things because, for example, you search for element 11 in the list [10, [11], [12], ...] -- and this is False . 您找不到任何东西是因为,例如,您在列表[10,[11],[12],...]中搜索元素11 –这是False [11] is an element of the latter list, but 11 is not. [11]是后一个列表的元素,但11不是。

See this lovely debug blog for help. 请参阅这个可爱的调试博客以获取帮助。

I've done a little debugging, including changing some variable names to something more meaningful. 我做了一些调试,包括将一些变量名更改为更有意义的名称。 Here's what I have at the moment, strictly low-tech print statements. 这是我目前所拥有的,严格的低技术印刷声明。

graphed = {
    1: [25, 30], 2: [11], 3: [13], 4: [17], 5: [17],
    6: [26], 7: [11, 12], 8: [10, 13], 9: [14, 26],
   10: [8, 11, 15], 11: [2, 7, 10], 12: [7, 16, 17],
   13: [3, 8, 14], 14: [9, 13, 20], 15: [10, 19],
   16: [12, 18], 17: [4, 5, 12], 18: [16, 21, 22],
   19: [15, 28, 29], 20: [14, 25], 21: [18, 23],
   22: [18, 24], 23: [21, 27], 24: [22, 27], 25: [1, 20],
   26: [6, 9], 27: [23, 24], 28: [19], 29: [19], 30: [1]
}

letters = {
    'S': [1],
    'C': [10, [11], [12], [13], [14], [15], [16], [17],
              [18], [19], [20], [21], [22], [23], [24],
              [25], [26], [27], [28], [29], [30] ],
    'O': [2, [3], [4], [5], [6]],
    'N': [7, [8], [9]]}


node_path = 'CO'

def dfs(graph, start, num, visited = None):
    print("ENTER dfs", start, num, visited)
    # depth first search for connected nodes
    start_ltr = node_path[num]
    end_ltr = node_path[(num+1)]
    if visited is None:
        visited = []

    if start in visited:
        return

    visited.append(start)
    # if start corresponds to first letter of string, continue
    print("  search for start node", start, "in list", start_ltr, letters.get(start_ltr))
    if start in letters.get(start_ltr):
        # find all nodes that it is connected too
        for each in [x for x in graph[start] if x not in visited]:
            print("    found", each, "in", graph[start]) 
            print("    search in list", end_ltr, letters.get(end_ltr))
            # if any of the connected nodes correspond to
            #   the next letter of string, continue...
            if [each] in letters.get(end_ltr):
                dfs(graph, each, (num+1), visited) #recursion

    print("LEAVE dfs", visited)
    return visited

lst1 = []
for i in range(1,15):    # I cut back the list for less output.
     lst1.append(dfs(graphed, i, 0))
print(lst1)

Output: 输出:

$ python3 so.py
ENTER dfs 1 0 None
  search for start node 1 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [1]
ENTER dfs 2 0 None
  search for start node 2 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [2]
ENTER dfs 3 0 None
  search for start node 3 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [3]
ENTER dfs 4 0 None
  search for start node 4 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [4]
ENTER dfs 5 0 None
  search for start node 5 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [5]
ENTER dfs 6 0 None
  search for start node 6 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [6]
ENTER dfs 7 0 None
  search for start node 7 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [7]
ENTER dfs 8 0 None
  search for start node 8 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [8]
ENTER dfs 9 0 None
  search for start node 9 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [9]
ENTER dfs 10 0 None
  search for start node 10 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
    found 8 in [8, 11, 15]
    search in list O [2, [3], [4], [5], [6]]
    found 11 in [8, 11, 15]
    search in list O [2, [3], [4], [5], [6]]
    found 15 in [8, 11, 15]
    search in list O [2, [3], [4], [5], [6]]
LEAVE dfs [10]
ENTER dfs 11 0 None
  search for start node 11 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [11]
ENTER dfs 12 0 None
  search for start node 12 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [12]
ENTER dfs 13 0 None
  search for start node 13 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [13]
ENTER dfs 14 0 None
  search for start node 14 in list C [10, [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30]]
LEAVE dfs [14]
[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14]]

Does that get you moving? 那会让你动起来吗?

Your letters dictionary is malformed. 您的letters词典格式错误。

'C': [10, [11], [12], [13], [14], [15], [16], [17],
          [18], [19], [20], [21], [22], [23], [24],
          [25], [26], [27], [28], [29], [30] ],
'O': [2, [3], [4], [5], [6]],
'N': [7, [8], [9]]}

Note how the first number for each letter is directly in the top-level list, but every other entry is in a sublist by itself. 请注意,每个字母的第一个数字如何直接位于顶层列表中,而其他所有条目本身都位于子列表中。 As a result, if start in letters.get(k) will be false for every C node that potentially connects to an O. 结果, if start in letters.get(k)if start in letters.get(k)对于可能连接到O的每个C节点, if start in letters.get(k)将为false。

>>> 10 in letters.get("C")
True
>>> 11 in letters.get("C")
False

So I changed the dictionary to this: 因此,我将字典更改为:

letters = {
    'S': [1],
    'C': [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
    'O': [2, 3, 4, 5, 6],
    'N': [7, 8, 9]}

You'll have to change this line accordingly: 您必须相应地更改此行:

if [each] in letters.get(y):

To

if each in letters.get(y):

Also, to get the results of each recursion call to actually be passed back up, I had to change this line: 另外,要使每个递归调用的结果实际传递回去,我必须更改此行:

dfs(graph, each, (num+1), visited) #recursion  

To

return dfs(graph, each, (num+1), visited) #recursion

Finally, add a special case at the top of the method for when all of some_string has been found: 最后,在找到所有some_string情况下,在方法顶部添加一个特殊情况:

def dfs(graph, start, num, visited = None):
    # depth first search for connected nodes
    if (num+1 == len(some_string)):
        return visited + [start]

At this point, the search was successful, so there are no more letters to search for! 至此,搜索成功,因此不再需要搜索字母!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM