【问题标题】:Need to generate possible trees from list需要从列表中生成可能的树
【发布时间】:2017-04-13 00:38:33
【问题描述】:

我想从一个整数列表[Int] -> [T] 中生成所有可能的树,但我只生成一棵树。

1           1
2           2
3           5
4          14
5          42

喜欢这些加泰罗尼亚数字。如果我的列表大小是 3,我想生成 5 棵可能的树,如果是 4 - 14 棵可能的树。

代码:

data T = N T T | L Int deriving (Show)
toT :: [Int] -> T
toT [] = L 0
toT [n] = L n
toT ns = T (toT (take mid ns)) (toT (drop (mid+1) ns))
where
mid = length ns div 2

例如:toT [1..3]

输出:N (L 1) (N (L 2) (L 3))N (N (L 1) (L 2)) (L 3)

现在我是这样做的

     toTree [] = error "!!"
     toTree [n] = Leaf n
     toTree ns = Node leftTree rightTree
     where 
     leftTree = toTree $ take (length(ns)-1) ns
     rightTree = toTree $ drop (length(ns)-1) ns` ı want ns length contiue descend one point recursive but ı didnt

我怎么能做到这一点?在递归中我将发送相同的列表但长度将下降我再次发送 [1,2,3] 大小 3 我发送 [1,2,3] 长度 2

【问题讨论】:

  • 实际上有 n!*C(n-1) 棵不同的树,有 n 个叶子; C(n-1) 个形状,n!在叶子中放置 n 个整数的方法。
  • 这也不像把你的列表分成两半那么简单;每个子树中有 k=1,...,n-1 个叶子的形状,而不仅仅是每个子树中的 n/2 个叶子。
  • @chepner 显示的可能树形状的数字对应于将值存储在节点中并具有空叶子的二叉树:data Tree a = Branch a (Tree a) (Tree a) | Empty
  • 在您的示例中,您使用您的数据类型显示了 3 个整数的 2 种可能的树形,但之前您提到了 5(表格也显示了 5)。哪个是正确的,数据类型还是表格?
  • 这样的桌子尺寸 1 树 1, 尺寸 2 树 1, 尺寸 3 树 2, 尺寸 4 树 5 尺寸 5 树 14 sory for msitake

标签: haskell tree enumeration template-haskell catalan


【解决方案1】:

需要发生的是,列表需要在每个可能的点进行拆分,这样做会使列表更小。子列表的树需要累加,然后将所有内容组合起来。

data Tree
  = L {-# UNPACK #-} !Int
  | N !Tree !Tree
  deriving (Eq, Ord, Read, Show)

-- Convert a list of Ints into a list of Trees containing the given list.
toTrees :: [Int] -> [Tree]

-- We start with the base cases: 0 and 1 elements. Because there are no
-- trees of 0 length, it returns the empty list in that case.
toTrees [] = []
toTrees [x] = [L x]

-- There is at least two elements in this list, so the split into nonempty
-- lists contains at least one element.
toTrees (x:xs@(y:ys)) = let
  -- splitWith uses a difference list to accumulate the left end of the
  -- split list.
  splitWith :: ([a] -> [a]) -> [a] -> [([a], [a])]
  splitWith fn [] = []
  splitWith fn as@(a:as') = (fn [], as):splitWith (fn . (:) a) as'

  -- Now we use a list comprehension to take the list of trees from each
  -- split sublist.
  in [
    N tl tr |
    (ll, lr) <- ([x], xs):splitWith ((:) x . (:) y) ys,
    tl <- toTrees ll,
    tr <- toTrees lr
  ]

这给出了预期的结果:

GHCi> toTrees [1, 2, 3, 4, 5]
[N (L 1) (N (L 2) (N (L 3) (N (L 4) (L 5)))),N (L 1) (N (L 2) (N (N (L 3) (L 4)) (L 5))),
 N (L 1) (N (N (L 2) (L 3)) (N (L 4) (L 5))),N (L 1) (N (N (L 2) (N (L 3) (L 4))) (L 5)),
 N (L 1) (N (N (N (L 2) (L 3)) (L 4)) (L 5)),N (N (L 1) (L 2)) (N (L 3) (N (L 4) (L 5))),
 N (N (L 1) (L 2)) (N (N (L 3) (L 4)) (L 5)),N (N (L 1) (N (L 2) (L 3))) (N (L 4) (L 5)),
 N (N (N (L 1) (L 2)) (L 3)) (N (L 4) (L 5)),N (N (L 1) (N (L 2) (N (L 3) (L 4)))) (L 5),
 N (N (L 1) (N (N (L 2) (L 3)) (L 4))) (L 5),N (N (N (L 1) (L 2)) (N (L 3) (L 4))) (L 5),
 N (N (N (L 1) (N (L 2) (L 3))) (L 4)) (L 5),N (N (N (N (L 1) (L 2)) (L 3)) (L 4)) (L 5)]
GHCi> length it
14

【讨论】:

    【解决方案2】:

    我更新了您的代码,它似乎对我有用。你能检查一下这是否符合你的期望吗?

    import Data.List
    
    data Tree = Node Tree Tree | Leaf Int deriving (Show)
    
    toTree :: [Int] -> Tree
    toTree [] = Leaf 0
    toTree [n] = Leaf n
    toTree ns = Node leftTree rightTree
        where midIndex = (length ns) `div` 2
              leftTree = toTree $ take midIndex ns
              rightTree = toTree $ drop (midIndex+1) ns
    
    allTrees :: [Int] -> [Tree]
    allTrees xs = map toTree $ permutations xs
    
    main = print $ allTrees [1..4]
    

    【讨论】:

    • 只看toTree的类型很明显它不能满足“生成所有可能的树”的期望。
    • 谢谢,但这会产生 [1..3] 6 树,但我想要前 [1..3] (N L1) (N (L2) (L3)) 和 N(N ( L1) (L2)) (L3)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多