如何使用算法BFS指示生成树的预订

时间:2012-01-14 21:54:58

标签: c++ breadth-first-search spanning-tree modified-preorder-tree-t

我正在用c ++实现BFS算法来查找生成树,生成树的输出应该预先显示,但我对实现有疑问,如果没有我可以构建一个树确切知道每个节点有多少个孩子?考虑树结构递归树的数据结构可以写成:

typedef struct node 
{
        int val;
        struct node *left, *right;
}*tree; //tree has been typedefed as a node pointer.

但是不要认为它像以前提到的那样有效。

这是我按顺序返回树的函数:

void preorder(tree t) 
{
        if(t == NULL)
                return;
        printf("%d ", t->val);
        preorder(t->left);
        preorder(t->right);
}

我也想知道是否有任何方法可以在不使用树结构的情况下对节点进行预订。

1 个答案:

答案 0 :(得分:3)

我在帖子中看到了两个具体问题:

  1. 是否可以在树中使用两个以上子项的数据结构?当然这是可能的。有趣的是,甚至可以使用您发布的节点结构!只需将left指针视为指向第一个子节点的指针,并将right指针指向下一个兄弟节点。由于广度优先搜索图形会隐式构建生成树,因此如果您实际以某种方式表示它,则可以按预先排序此树。
  2. 你可以在不使用树形结构的情况下进行预订吗?是的,这也是可能的。从本质上讲,DFS和BFS在概念上并没有什么不同:您只需要一个数据结构来维护下一个要访问的节点。对于DFS,这是一个堆栈,对于BFS,这是一个队列。如果在将数据结构插入到维护要访问的节点的数据结构中时发出节点编号,则会获得树的预先排序(即,您访问父节点之后的节点的所有子节点)。
  3. 要在第二点上展开一点:树的预订步行只意味着在子节点之前处理每个节点。当您进行图形搜索时,您希望遍历图形的连接组件,只访问每个节点一次,就可以有效地创建隐式树。也就是说,您的起始节点将成为树的根节点。每当您访问节点时,您都​​会搜索尚未访问过的相邻节点,即未标记的节点。如果存在此类节点,则事件边缘将成为树节点,并标记该节点。由于始终只有一个节点被主动保持,因此需要记住未处理的节点,但是,在某些数据结构中,例如,堆栈或队列(而不是显式使用堆栈,您可以执行递归,隐式创建堆栈)。现在,如果您在第一次看到节点时发出节点编号,则在其子节点之前清楚地处理它,即您最终将节点编号写为预订顺序。

    如果您不明白这一点,请掏出一张纸并绘制图表和队列:

    • 带有空心圆的节点及其旁边的节点编号
    • 细线边缘
    • 队列只是在开头不包含任何内容的矩形

    现在选择一个节点成为搜索的起始节点,该节点与树的根节点相同。将其编号写入队列中的第一个空位置并标记即填充节点。现在继续搜索:

    • 查看队列前面指示的节点,找到未填充的相邻节点:
      • 将节点附加到队列的后面(即矩形中最后一个节点的正后方)
      • 标记(即填充)节点
      • 使连接两个节点的线条更粗:现在是树边缘
    • 如果没有其他未标记的相邻节点勾选队列中的前节点(即将其从队列中删除)并继续前进到下一个节点,直到没有其他节点

    现在,队列矩形包含生成树的前序步行,这是由图的广度优先搜索所暗示的。使用较粗的线条可以看到生成树。如果您将队列的矩形视为堆栈,该算法也会起作用,但是它会有点麻烦,因为您最终还是要在处理的节点之间勾选节点:而不是查看第一个未查找的节点,您将看到最后一个未被攻击的节点。

    使用图算法时,我发现可视化算法非常有用。虽然让计算机维护绘图会很好,但是在纸上绘制东西并且可能通过一些带标签的铅笔指示活动节点的低技术替代方案也可行,如果不是更好的话。

    只需对代码发表评论:无论何时阅读任何输入,请确保您已成功读取数据。顺便说一下,你的代码显然只是C而不是C ++代码:C ++中没有可变长度数组。在C ++中,您将使用std::vector<int> followOrder(vertexNumber)而不是int followOrder[vertexNumber]。有趣的是,代码不是C,因为它使用例如std::queue<int>