【问题标题】:How to construct a tree with it's BFS and DFS traversal如何用 BFS 和 DFS 遍历构造一棵树
【发布时间】:2015-09-24 16:48:20
【问题描述】:

我有 BFSDFS 遍历一棵树。如何从这些遍历中重建树?

例如:

BFS Traversal : 4 3 5 1 2 8 7 6

DFS Traversal : 4 3 1 7 2 6 5 8

那么树会像下面这样:

       4
      / \
     3   5    
    / \   \    
   2   1   8
   |   |         
   6   7      

【问题讨论】:

标签: algorithm graph depth-first-search breadth-first-search tree-traversal


【解决方案1】:

这只有在 BFS 和 DFS 使用完全相同相同的顺序来遍历子节点时才有可能:

规则 1:

BFS Traversal : 4 3 5 1 2 8 7 6
                | | |
                | | |-------|
                | |         |
DFS Traversal : 4|3 1 7 2 6|5 8

正如这个例子所示,我们可以很容易地知道(3 , 1 , 7 , 2 , 6) 属于一个以 3 为根的子树。由于 1 也是该子树的一部分,因此我们可以推导出 3 和 5 是 4 的唯一子节点。

规则 2:

BFS Traversal : 4 3 5 1 2 8 7 6
                | |   |
                | | |-|
                | | |        
DFS Traversal : 4 3 1 7 2 6 5 8

这样,我们可以证明 3 和 5 是 4 的孩子。

这也可以仅使用包含属于同一子树的节点的 BFS 和 DFS 的子集来完成(此示例是在规则 1 的演示中找到的子树):

使用规则 1:

BFS Traversal: 1 2 7 6
               | |
               | |-|
               |   |
DFS Traversal: 1|7|2 6

这表明 7 是 1 的唯一孩子。

使用规则 2:

BFS Traversal: 1 2 7 6
               |   |
               | |-|
               | |  
DFS Traversal: 1 7 2 6

因此 1 和 2 是同一个父级(即 3 个)的子级。

翻译成伪代码如下:

addchild(int parent, int child) := add the child to the specified parent node

void process(int[] bfs , int[] dfs)
    int root = bfs[0]

    //find all peers (nodes with the same level and parent in the tree) using Rule 2
    int at = bfs.find(dfs[2])
    int peers[at - 1]
    for int i in [1 , at[
        peers[i - 1] = bfs[i]
        addchild(root , bfs[i])

    //for each of the childtree of the tree find it's children using Rule 1
    for int i in [0 , length(peers)[
        //all nodes that are either peers[i] or a child of peers[i]
        int[] children_dfs = dfs.subset(dfs.find(peers[i]) , (i < length(peers) - 1 ? dfs.find(peers[i + 1]) : length(dfs)) - 1)
        //a subset of bfs containing peers[i] and it's children in the order they have in bfs
        int[] children_bfs = bfs.allMatchingInOrder(children_dfs)

        //generate the subtree
        process(children_bfs , children_dfs)

【讨论】:

  • 这里的allMatchingInOrder() 是什么意思:int[] children_bfs = bfs.allMatchingInOrder(children_dfs)
  • @madMDT 你纠正的“错误”没有错误,但遵循数学符号,所以[x , y[ 表示范围x 到专门yallMatchingInOrder 应该生成一个数组,其中包含参数中的所有值,这些值按照它们在调用它的数组中出现的顺序排列。例如:{0 , 1 , 2 , 3 , 4}.allMatchingInOrder({1 , 4 , 3}) 将返回 {1 , 3 , 4}subset()-函数应该生成一个子集,从第一个参数指定的索引开始,到第二个参数给出的索引结束(sry,这里实际上有一个错误)。
  • 如果我在 [1 中采用 i ,在 [ 在规则 1 步骤中,那么我怎样才能采用 peers[i] 相同的步骤?看起来 peers[0] 将丢失!
  • 如果 BFS 遍历是 1、2、3 并且 DFS 遍历是 1、2、3,你能解释一下你的算法会给出什么吗?我相信这里有两棵独特的树(也许没关系?OP没有说“生成独特的树”)。
  • 顺便问一下,你在哪里找到了 [a, b[ 间隔符号?我见过更常见的 [a, b)。
猜你喜欢
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2022-06-27
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
相关资源
最近更新 更多