【问题标题】:How to indicate preorder of a spanning tree using the algorithm BFS如何使用算法 BFS 指示生成树的前序
【发布时间】:2023-03-12 11:44:01
【问题描述】:

我正在 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);
}

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

【问题讨论】:

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


    【解决方案1】:

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

    1. 是否可以在一个树中拥有一个使用两个以上子级的数据结构?当然这是可能的。有趣的是,您发布的节点结构甚至是可能的!只需将left 指针视为指向第一个子节点的指针,将right 指针视为指向下一个兄弟节点的指针。由于图的广度优先搜索隐式地构建了一个生成树,因此如果您实际上以某种方式表示它,您就可以按顺序遍历这棵树。
    2. 您可以在不使用树结构的情况下进行预购游走吗?是的,这也是可能的。本质上,DFS 和 BFS 在概念上并没有什么不同:你只是有一个数据结构来维护接下来要访问的节点。对于 DFS,这是一个堆栈,对于 BFS,这是一个队列。如果您在将节点编号插入维护要访问的节点的数据结构中时发出节点编号,您将获得树的预排序(即您在父节点之后访问节点的所有子节点)。

    稍微扩展第二点:树的前序遍历只是意味着每个节点在其子节点之前被处理。当您进行图搜索时,您希望遍历图的连接组件,只访问每个节点一次,您实际上创建了一个隐式树。也就是说,您的起始节点成为树的根节点。每当您访问一个节点时,您都​​会搜索尚未访问过的相邻节点,即未标记的节点。如果存在这样的节点,则入射边成为树节点,您标记该节点。由于始终只有一个节点被主动持有,因此您需要记住尚未处理的节点,但在某些数据结构中,例如堆栈或队列(而不是显式使用堆栈,您可以进行隐式创建堆栈的递归)。现在,如果您在第一次看到一个节点时发出节点编号,您会在其子节点之前清楚地处理它,即您最终将节点编号写入前序遍历的顺序。

    如果你不明白这一点,请拿出一张纸,画一个图表和一个队列:

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

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

    • 查看队列前面指示的节点,找到一个未填满的相邻节点:
      • 将节点追加到队列的后面(即矩形中最后一个节点的后面)
      • 标记(即填充)节点
      • 把连接两个节点的线加粗:现在是树的边缘
    • 如果没有其他未标记的相邻节点,则将队列中的前节点打勾(即从队列中删除)并移至下一个节点,直到没有其他节点为止

    现在队列矩形包含由图的广度优先搜索暗示的生成树的前序游走。使用较粗的线可以看到生成树。如果您将队列的矩形视为堆栈,该算法也将起作用,但它会有点混乱,因为您最终会在仍待处理的节点之间勾选节点:而不是查看第一个未勾选的节点,您将查看最后一个未勾选的节点。

    在使用图形算法时,我发现将算法可视化非常有帮助。虽然让计算机维护绘图会很好,但在纸上绘制东西并可能通过一些标记的铅笔指示活动节点的低技术替代方案即使不是更好也可以工作。

    只是对代码的注释:每当您读取任何输入时,请确保您已成功读取数据。顺便说一句,您的代码显然只是 C 而不是 C++ 代码:可变长度数组在 C++ 中不可用。在 C++ 中,您将使用 std::vector<int> followOrder(vertexNumber) 而不是 int followOrder[vertexNumber]。有趣的是,代码也不是 C,因为它使用例如std::queue<int>.

    【讨论】:

    • 对于你的第二个答案,我的代码怎么做?,我真的不明白你的意思,你能不能更具体和详细一点?我不明白您的意思:“如果您在将节点号插入维护要访问的节点的数据结构中时发出节点号。”
    • 按照我说的,你应该在当前节点的子节点入队之前打印,即代码的一部分:inline for(i=0; i<V; i++){ if( BFS_graph[i][node]) myQueue.push(i); if( BFS_graph[node][i]) myQueue.push(i); } 但我真的不明白,我坚持这个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多