【问题标题】:Finding all subtrees of n-ary tree查找n叉树的所有子树
【发布时间】:2017-01-29 02:21:48
【问题描述】:

我正在尝试查找 n 叉树的所有子树。只有 BFS 或 DFS 不起作用。因为树不是二元的。例如:

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

我想显示包括这个在内的所有子树

        1
     /    \
    2      3
     \     |
      6    7

如何从原始子树中提取此子树?

【问题讨论】:

  • 您应该记住,所有子树的数量通常是指数级的。所以如果你在一棵大树上调用它,你就完蛋了。
  • BFS 和 DFS 适用于任何图形。树是否是二叉树根本不重要
  • 你可以为二叉树做吗?非二叉树有什么根本不同?
  • 你的解释我一个字都听不懂。请展示你的二叉树算法,并指出你不能为非二叉树修改的行。
  • 您声称您可以对二叉树执行此操作,但您不能将其转换为适用于任意树的东西。如果您展示它并指出您无法转换的步骤,我可以尝试帮助您转换您的算法。我还可以用几行 Haskell 向你展示一个现成的算法,它会有帮助吗?不过,我想先尝试第一个选项。 (我还注意到您正在使用子树的图论定义,但不清楚您是否指有根子树;请澄清)。

标签: algorithm tree


【解决方案1】:

要生成给定树的所有(图论)子树,我需要一些辅助概念。

子树是一棵树的连接子图,或者等效地,一个子图也是一棵树。

有根树的后代树要么是原始的有根树本身,要么是作为其顶点之一的子节点的有根树。 (这里不会给出确切的定义,因为从树作为递归数据结构的概念应该很清楚)。

有根树的有根子树是与原始有根树具有相同根的子树。我们可以通过计算根的(一些)直接子节​​点的有根子树,并将这些子树与原始根组合来获得有根树的有根子树。

请注意,任意子树是后代树的有根子树。

为简单起见,我将处理非空树。

-- a (rooted) tree is a root node and a list of children attached to it
data Tree a = Node a [Tree a] deriving Show

得到后代很简单:

-- a descendant tree  is either a tree itself, 
-- or a descendant of a child of its root
descendants :: Tree a -> [Tree a]
descendants t@(Node a ts) = t : concatMap descendants ts

有根子树并不难:

-- to get a rooted subtree, take a root, choose which children to 
-- retain, take a rooted subtree of each retained child, 
-- and attach the results to a copy of the root

rootedSubtrees :: Tree a -> [Tree a]
rootedSubtrees (Node a ts) = [Node a tts | 
                              tts <- choices (map rootedSubtrees ts)]

-- this function receives a list of lists and generates all lists that 
-- contain 0 or 1 element from each input list
-- for ex. choices ["ab", "cd"] = ["","c","d","a","ac","ad","b","bc","bd"]
choices :: [[a]] -> [[a]]
choices [] = [[]]
choices (xs:xxs) = cs ++ [x:c | x <- xs, c <- cs] where cs = choices xxs

最后,任意子树的列表是

subtrees :: Tree a -> [Tree a]
subtrees t = concatMap rootedSubtrees (descendants t)

【讨论】:

    【解决方案2】:

    您可以执行以下操作。

    • 对于树中的每个顶点,您决定是切割以顶点为根的子树还是继续探索。您的选择数量约为 2^(节点数)。请注意,确切地说是 2^(节点数)(虽然较小,但仍然是指数级的),因为在您切割子树后,您不会探索它。
    • 对于每个顶点的选择配置,使用DFS 打印树。

    您的示例是切割根为458 的子树的配置。

    可以通过为每个节点设置标志来隐式完成切割。

    【讨论】:

      猜你喜欢
      • 2015-10-07
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多