广度优先搜索没有 return 节点的正确排序

Breadth First Search does not return the correct ordering for nodes

我已经实现了一个看起来像这样的树:

               1

    2          3          4

 5     6               7      8

我想按广度打印。这是我的代码:

class Node:
    def __init__(self):
        self.data = None
        self.children = []


class Tree:
    def __init__(self):
        self.root = Node()

    def build(self):
        self.root.data = 1
        self.root.children.append(Node())
        self.root.children.append(Node())
        self.root.children.append(Node())
        self.root.children[0].data = 2
        self.root.children[1].data = 3
        self.root.children[2].data = 4

        self.root.children[0].children.append(Node())
        self.root.children[0].children.append(Node())

        self.root.children[2].children.append(Node())
        self.root.children[2].children.append(Node())

        self.root.children[0].children[0].data = 5
        self.root.children[0].children[1].data = 6

        self.root.children[2].children[0].data = 7
        self.root.children[2].children[1].data = 8
        return


    def traverseBF(self, node):
        li = []
        trav = []
        li.append(node)
        while len(li) != 0:
            for x in li:
                trav.append(x.data)
                for z in x.children:
                    li.append(z)
                # map(lambda z: li.append(z), x.children)
                li.remove(x)
        print(trav)



t = Tree()
t.build()
t.traverseBF(t.root)

输出为:[1, 3, 2, 5, 4, 7, 6, 8]

我的问题是:

  1. 为什么 3 在 2 之前插入 trav[],即使在 root.children 中顺序是 [2,3,4]
  2. 为什么注释掉的 map 函数给出的结果与上面的 for 循环不一样?

问题在于您如何管理队列。使用单个 while 循环来检查列表的长度。在 while 内,弹出第一个节点,然后用弹出节点的子节点扩展队列。您的函数应如下所示:

def traverseBF(self, node):
    li = []
    trav = []
    li.append(node)
    while len(li) != 0:
        x = li.pop(0)          # pop the first item
        li.extend(x.children)  # extend the queue with children
        trav.append(x.data)
    print(trav)

这样,t.traverseBF(t.root) 打印出 [1, 2, 3, 4, 5, 6, 7, 8]


这是您的代码的“更简洁”版本。我喜欢生成器,所以我把它变成了一个生成器,returns BFS 中的节点值一一排序:

def bfs(node):
    q = [node]
    while q:
        n = q.pop(0)
        q.extend(n.children)
        yield n.data

[*bfs(t.root)]
# [1, 2, 3, 4, 5, 6, 7, 8]