我有一个树的数据结构,其节点有一个或两个子节点。我可以生成一个给定最大深度的随机树。现在我想用给定的最大节点数(/ leafes)生成这些随机三。这是我的结构:
import System.Random
data Tree a = Leaf
| NodeTwo (Tree a) (Tree a)
| NodeOne (Tree a)
deriving (Show)
create :: RandomGen g => Int -> Int -> Int -> Int -> g -> Tree a
create depth maxNodeOne maxNodeTwo maxLeaf g
| (depth == 0) = Leaf
| (x >= a && x < c && (maxNodeTwo /= 0))
= let (g1, g2) = split g in
NodeTwo (create (depth -1) maxNodeOne (maxNodeTwo-1)
maxLeaf g1) (create (depth -1) maxNodeOne
(maxNodeTwo-1) maxLeaf g2)
|(x >= c && x < 2*c && (maxNodeOne /= 0))
= NodeOne (create (depth -1)
(maxNodeOne -1) maxNodeTwo maxLeaf g')
| otherwise = Leaf
where (x, g') = next g
(a, b) = genRange g
c = (b - a) `div` 3
countFnk :: Tree a -> Int
countFnk (Leaf) = 0
countFnk (NodeOne a) = countFnk a
countFnk (NodeTwo a b) = 1 + countFnk a + countFnk b
countLam :: Tree a -> Int
countLam (Leaf) = 0
countLam (NodeOne a) = 1 + countLam a
countLam (NodeTwo a b) = countLam a + countLam b
countLeaf :: Tree a -> Int
countLeaf (Leaf) = 1
countLeaf (NodeOne a) = countLeaf a
countLeaf (NodeTwo a b) = countLeaf a + countLeaf b
此尝试未通过。我不知道如何减少递归中节点的计数器。我还有一些函数可以获得节点数量(/ leafes),但我不知道如何在我的create函数中使用这些函数,因为它们需要一个完成的树来扫描。 谢谢你的帮助。
答案 0 :(得分:3)
最明显的问题出在NodeTwo
案例中。您到达那个点时,需要花费NodeTwo
和NodeOne
s的“预算”。但是你告诉你新树的两个分支都是一样的:“随意花费整个预算”!当然,如果他们都这样做,你最终会花费一倍的预算。
您需要一些方法来协商树的每个分支的预算。你可以通过多种方式做到这一点;例如,让一个分支访问整个预算,并将剩余的内容提供给第二个分支。或者您可以在创建任一分支之前决定如何在它们之间划分预算,并为每个分支仅提供总预算的一部分。
这两种方法中的任何一种都可能在您的随机性中引入一些偏差,这对您来说可能或不重要。你应该想办法以一种产生你想要的随机树种的方式来处理预算会计。
一旦你修复了这个问题,你就会遇到其他问题:有些约束集无法构建适合它们的树!最值得注意的是,如果maxLeaf
为零,则根本无法创建任何类型的树,因为每个树在某处至少有一个叶节点。你必须要小心,不要用太少的叶片来构建任何子树,让它们终止。