邻接表构建

时间:2019-03-24 10:15:38

标签: python python-3.x for-loop

我在了解

的最终输出时遇到问题
for i in edgeList:
    adjacencyList[i[0]].append(i[0])

在下面的代码中。我尝试在每一行中打印出语句以尝试理解,但仍然感到困惑。

    vertexList = ["0","1","2","3","4","5","6"]
    edgeList = [(0,1), (0,2),(1,0), (1,3), (2,0), (2,4), (2,5), (3,1), (4,2), (4,6), (5,2), (6,4)]

    adjacencyList = [[] for vertex in vertexList]

    for i in edgeList:
        adjacencyList[i[0]].append(i[1])

    print(adjacencyList)

Output: [[1, 2], [0, 3], [0, 4, 5], [1], [2, 6], [2], [4]]

这是否由于列表理解而在for循环中发生了for循环?欣赏是否有人可以说明这里发生的事情。 (这与图论中的BFS有关)

2 个答案:

答案 0 :(得分:2)

您的adjacencyList构造错误。

替换 adjacencyList[i[0]].append(i[0])adjacencyList[i[0]].append(i[1])。我在另一个内部看不到任何for循环。您的时间复杂度为O(n)

adjacencyList的目的是存储给定节点的所有相邻节点,在您的情况下,它是列表的索引。

更改后,您的输出应为

  

[[1,2],[0,3],[0,4,5],[1],[2,6],[2],[4]]

由此您可以将0解释为具有1和2作为邻居。 2具有0和3个邻居,3具有0,4和5作为邻居,依此类推。

请注意,如果您有{2,60,1000,4}之类的节点,则此方法将失败。在这种情况下,最好使用节点字典和邻居列表。

答案 1 :(得分:2)

graphviz是可视化图形问题的一个很好的工具,它带有dot命令。首先创建edgelist.dot,其中包含edgeList变量中的所有边:

digraph G {
    0 -> 1
    0 -> 2
    1 -> 0
    1 -> 3
    2 -> 0
    2 -> 4
    2 -> 5
    3 -> 1
    4 -> 2
    4 -> 6
    5 -> 2
    6 -> 4
}

(您可以通过较短的方式来编写此代码)。 然后通过dot填充它:

c:\srv\tmp> dot -Tsvg -o edgelist.svg edgelist.dot

,然后打开创建的edgelist.svg文件:

graph created by graphviz

邻接列表是可以从特定节点访问的节点列表,例如对于节点0,有指向节点12的箭头,因此adjacencyList[0],即节点0的邻接列表应为[1, 2]

类似地,从节点2出发的箭头到达节点045,因此adjacencyList[2]应该是[0, 4, 5]

按顺序依次遍历每个节点,邻接列表以以下结尾:

            [[1, 2], [0, 3], [0, 4, 5], [1], [2, 6], [2], [4]]
             ^       ^       ^          ^    ^       ^    ^
item/index:  0       1       2          3    4       5    6

在您的代码中,此行:

adjacencyList = [[] for vertex in vertexList]

仅将adjacencyList创建为空列表([])的列表,其长度等于顶点数。

然后进行循环:

for i in edgeList:
    adjacencyList[i[0]].append(i[0])

试图填充它。要找出问题所在,我们可以重写for循环,以便将edgeList中的边缘解包:

for (start, end) in edgeList:
    adjacencyList[start].append(..?..)

显然..?..应该是end而不是开始:

for start, end in edgeList:
    adjacencyList[start].append(end)

现在您可以看到for循环正在执行我们在上面手动执行的操作,对于每个边(start, end),它会将end添加到start的邻接列表中。

附录:对于顶点(01等)的值与数组索引相同的情况,您的代码效果很好。尽管效率很高,但它在教学上可能不是可取的(或者也许是,我不知道;-)在任何情况下,如果我们重命名顶点,以使0变成"A",{{1 }}变成1等,您需要为邻接表使用其他数据结构,例如:

"B"

打印:

from collections import defaultdict

edgeList = [("A", "B"),
            ("A", "C"),
            ("B","A"), ("B","D"),
            ("C","A"), ("C","E"), ("C","F"),
            ("D","B"),
            ("E","C"), ("E","G"),
            ("F","C"),
            ("G","E")]

adjacencyList = defaultdict(list)

for start, end in edgeList:
    adjacencyList[start].append(end)

print(sorted(adjacencyList.items()))

表示[('A', ['B', 'C']), ('B', ['A', 'D']), ('C', ['A', 'E', 'F']), ('D', ['B']), ('E', ['C', 'G']), ('F', ['C']), ('G', ['E'])] 的邻接列表是'A'等。

有可能(可能有益于运行时间)将此版本转换为第一个版本(尤其是比Python更静态的语言)。