如何使用链表实现 BFS 树算法?

How do I implement a BFS tree algorithm using a linked list?

我正在尝试使用链表输出 BFS 树。但是,我在实现该算法时遇到了麻烦。我对如何将链表图实现到算法中感到困惑。我不太确定如何创建一个由 false 和 true 数组组成的矩阵,然后遍历它以根据所选的子节点找到 false 节点。我应该收到的输出是

0: 1 3
1: 2 4
3:
4:

代码:

class Node:
    def __init__(self, value):
        self.vertex = value
        self.next = None


class AdjGraph:
    def __init__(self, data):
        self.data = data
        self.graph = [None] * self.data

    # Add edges
    def addEdge(self, vertice, edge):
        currNode = self.graph[vertice]
        newNode = Node(edge)
    
        if currNode == None:
            self.graph[vertice] = newNode 
            return
    
        while currNode != None:
            if currNode.next == None:
                currNode.next = newNode
                break
            currNode = currNode.next

    # Implement BFS Graph
    def bfs(self, s):
        # Set discovered[s] = true, discovered[v] = false for all other v
        discovered = [False] * self.graph
        discovered[s] = True
        # Intialize L[0] to consist of the single element s
        layer = []
        layer.append(s)
        # Set the counter i = 0
        i = 0
        # Set the current BFS tree T = None
        T = None

        # While L[i] is not empty
        while layer:
            # Initialize an empty list L[i+1]
            empty_list = layer[i+1]
            print (s, end = " ")
            # For each node u is an element of L[i]
            for u in layer[i]:
                # Consider each edge (u, v) incident to u
                if discovered[v] == False:
                    # Set discovered[v] = true
                    discovered[v] = True
                    # Add edge (u, v) to the tree T
                    T.append
                    # Add v to the list L[i+1]
                    empty_list.append(v)

    # Print the graph
    def printGraph(self):
        adj_list = "Adjacency List"
        for i in range(self.data):
            adj_list += "\n\nNode " + str(i) + ": "
            temp = self.graph[i]
            while temp:
                adj_list += str(temp.vertex) + " "
                temp = temp.next
        print(adj_list)


g = AdjGraph(5)
g.addEdge(0, 1)
g.addEdge(0, 3)
g.addEdge(1, 0)
g.addEdge(1, 2)
g.addEdge(1, 3)
g.addEdge(1, 4)
g.addEdge(2, 1)
g.addEdge(2, 4)
g.addEdge(3, 0)
g.addEdge(3, 1)
g.addEdge(3, 4)
g.addEdge(4, 1)
g.addEdge(4, 2)
g.addEdge(4, 3)
g.bfs(0)

您的 bfs 代码有很多问题。我不会一一列举,但是:

  • [False] * self.graph 没有意义,因为 self.graph 不是数字
  • layer[i+1]第一次求值时不存在
  • for u in layer[i] 不起作用,因为 layer[i] 是一个节点号 (s),并且不可迭代
  • empty_list 收到值,但从未使用过。
  • T.append 什么都不做。
  • 尽管尝试将数据放入 T,但从未使用过。
  • i 的值永远不会改变。
  • bfs 只修改局部变量而不会 return 任何东西。所以在它被调用之后,除了打印的节点号之外,与调用之前没有什么不同。但我想那只是为了调试目的,因为它不遵循输出格式。

正如我在评论中提到的,由于预期输出对应于由广度优先搜索 (BFS) 形成的搜索树,因此根据添加节点的顺序和访问顺序,输出可能会有所不同节点。

示例图如下所示:

        0-----1
         \   /|\
          \ / | \
           3--4--2

从节点 0 开始的 BFS 可以生成以下任一搜索树:

0-----1          0-----1
 \    |\          \     \
  \   | \          \     \
   3  4  2          3--4  2

这取决于节点1和节点3展开的顺序。第一棵树是节点1先展开的结果,第二棵树是节点3先展开的结果

现在,既然您想使用链表,我还应该提到 向链表添加 一个节点在 开始时更有效列表的 比最后(除非您还维护 tail 引用)。所以我建议不要使用 currNode 循环,而是 prepend 列表开头的新节点。这样就没有循环了。这当然会影响最终出现在列表中的节点的顺序。

以下代码将从图中删除 BFS 树中未使用的边。这样您就可以使用 printGraph 函数输出结果。

代码:

class Node:
    def __init__(self, value, nxt=None):
        self.vertex = value
        self.next = nxt


class AdjGraph:
    def __init__(self, size):
        self.size = size
        self.graph = [None] * self.size

    def addEdge(self, vertex, edge):
        # Prepend the new node to the linked list
        self.graph[vertex] = Node(edge, self.graph[vertex]) 

    def bfs(self, s):
        discovered = [False] * self.size
        discovered[s] = True
        layer = [s]

        while layer:
            empty_list = []
            for u in layer:
                keep = None # this will be the new (filtered) list for self.graph[u]
                v = self.graph[u]
                while v:
                    nxt = v.next
                    if not discovered[v.vertex]:
                        discovered[v.vertex] = True
                        empty_list.append(v.vertex)
                        # Prepend v to the keep linked list
                        v.next = keep
                        keep = v
                    v = nxt
                self.graph[u] = keep
            layer = empty_list  # start working with the next layer

    def printGraph(self):
        adj_list = "Adjacency List"
        for i in range(self.size):
            adj_list += "\nNode " + str(i) + ": "
            temp = self.graph[i]
            while temp:
                adj_list += str(temp.vertex) + " "
                temp = temp.next
        print(adj_list)


g = AdjGraph(5)
g.addEdge(0, 1)
g.addEdge(0, 3)
g.addEdge(1, 0)
g.addEdge(1, 2)
g.addEdge(1, 3)
g.addEdge(1, 4)
g.addEdge(2, 1)
g.addEdge(2, 4)
g.addEdge(3, 0)
g.addEdge(3, 1)
g.addEdge(3, 4)
g.addEdge(4, 1)
g.addEdge(4, 2)
g.addEdge(4, 3)
g.bfs(0)
g.printGraph()

输出:

Adjacency List
Node 0: 1 3 
Node 1: 2 
Node 2: 
Node 3: 4 
Node 4: