【问题标题】:BFS in binary tree二叉树中的 BFS
【发布时间】:2011-05-17 02:35:37
【问题描述】:

我正在尝试在二叉树中编写广度优先搜索的代码。我已将所有数据存储在一个队列中,但我不知道如何前往所有节点并使用它们的所有子节点。

这是我的 C 代码:

void breadthFirstSearch (btree *bt, queue **q) {
   if (bt != NULL) {

      //store the data to queue if there is

      if (bt->left != NULL) enqueue (q, bt->left->data);
      if (bt->right != NULL) enqueue (q, bt->right->data);

      //recursive

      if (bt->left != NULL) breadthFirstSearch (bt->left, q);
      if (bt->right != NULL) breadthFirstSearch (bt->right, q);
   }
}

我已将根数据排入队列,但仍无法正常工作。 谁能指出我的错误?

【问题讨论】:

    标签: c breadth-first-search


    【解决方案1】:

    无需递归即可轻松编写 BFS。只需使用队列来订购您的扩展:

    void BFS(btree *start)
    {
        std::deque<btree *> q;
        q.push_back(start);
        while (q.size() != 0)
        {
            btree *next = q.front();
            // you may want to print the current node here or do other processing
            q.pop_front();
            if (next->left)
                q.push_back(next->left);
            if (next->right)
                q.push_back(next->right);
        }
    }
    

    关键是不需要递归遍历树;您只需让您的数据结构处理您访问节点的顺序。

    请注意,我在这里使用的是 C++ 双端队列,但是任何可以让您将项目放在后面并从前面获取它们的东西都可以正常工作。

    【讨论】:

    • 谢谢,这帮助我在自己的实现中找到了一个小错误。
    【解决方案2】:
    void bfs_bintree (btree_t *head)
    {
      queue_t *q;
      btree_t *temp;
    
      q = queue_allocate ();
      queue_insert (q, head);
    
      while (!queue_is_empty (q))
      {
        temp = queue_remove (q);
    
        if (temp->left)
          queue_insert (temp->left);
    
        if (temp->right)
          queue_insert (temp->right);
      }
      queue_free (q);
      return;
    }
    

    首先将head 节点插入到队列中。当队列不为空时,循环将迭代。从头节点开始,在每次迭代中删除一个节点,并将非空子节点插入队列中。在每次迭代中,一个节点退出,其非空子节点被推送。在下一次迭代中,下一个发现的最旧顶点(现在位于队列的前面)被取出(按照它们被发现的顺序),然​​后对它们进行处理以检查它们的子节点。

                                    A
                                   / \
                                  /   \
                                 B     C
                                / \     \
                               /   \     \
                              D     E     F
                             / \         / \
                            /   \       /   \
                           G     H     I     J
    
    
    iteration  Vertex Selection Discovery Queue State
     initial                    :  A
        1            A          :  B C     {A is removed and its children inserted}
        2            B          :  C D E   {B is removed and its only child inserted}
        3            C          :  D E F   {C is removed and its children inserted}
        4            D          :  E F G H {D is removed and its children inserted}
        5            E          :  F G H   {E is removed and has not children}
        6            F          :  G H I J {F is removed and its children inserted}
        7            G          :  H I J   {G is removed has no children}
        8            H          :  I J     {H is removed has no children}
        9            I          :  J       {I is removed has no children}
        10           J          :  (empty) {J is removed has no children}
    

    当我们得到队列中没有更多发现的等待选择的顶点时,迭代停止,因此选择了在二叉树(图连接组件)中发现的所有顶点。

    我的代码首先传递队列中的节点,然后再次递归遍历这些子节点,从而创建 DFS 模式。如果必须进行递归,则需要检查队列是否为空作为基本条件。还要检查一下您是如何通过队列的,我认为这可能是不正确的。我会建议一个迭代的解决方案。

    【讨论】:

      【解决方案3】:

      您在这里没有进行广度优先遍历。相反,您将队列中的左右元素排入队列并移动到左子树。你先用尽左子树,然后再移动到右子树。

      编写一个过程来将节点排入队列。

      void breadthFirstSearch (btree *bt, queue **q) {
       btree *tmpNode;
       enqueue(q,bt); //Assuming your root node has data
      
       while (!isempty(q)) //Assume isempty returns false when queue is not empty
       {
        tmpNode = dequeue(q);
        //Do whatever you want to do with tmpNode->data
        enqueue(tmpNode->left);
        enqueue(tmpNode->right);
        /* If this is a acyclic graph(tree) then this procedure should do, else you have to mark the nodes you have visited in-order not to end in a cycle */
       }
      
      }
      
      int main()
      {
      breadthFirstSearch(bt,q)
      return 0
      }
      

      【讨论】:

      • 我还是不明白。如果你只是左右排队,难道队列中只有3个节点(根,根->左,根->右)。其余的不会插入队列中......
      • 我在代码片段中犯了一个错误。我必须检查 tempNode->left 和 tempNode->right 是否为空。
      • 它是这样工作的:假设你有一个完整的二叉树,有 7 个节点,从左到右编号为 1 到 7(即根节点为 1,右角的最后一个叶节点为 7)。您首先将根节点(编号为 1)推入队列中,然后将其出列处理元素将左(编号为 2)和右(编号为 3)的节点推入队列中。在下一次迭代中,您将队列中的第一个元素(编号为 2)出列,并将其左右元素排入队列,这些元素是编号为(4 和 5)的节点,在下一次迭代中,您将编号为 3 的节点出列,处理数据元素并推送编号的节点6 & 7.
      • 这个过程一直持续到队列清空。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 2016-08-18
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多