【问题标题】:F# Tree: Node InsertionF# 树:节点插入
【发布时间】:2014-11-27 15:09:24
【问题描述】:

这是一个延伸 F# Recursive Tree Validation 的问题,我昨天已经很好地回答了。

这个问题涉及在现有树中插入一个孩子。这是我想使用的更新类型:

type Name           = string
type BirthYear      = int
type FamilyTree     = Person of Name * BirthYear * Children
and Children        = FamilyTree list

我的最后一个问题是关于检查树的有效性,这是我决定采用的解决方案:

let rec checkAges minBirth = function
    | Person(_,b,_) :: t -> b >= minBirth && checkAges b t
    | [] -> true

let rec validate (Person(_,b,c)) =
    List.forall isWF c && checkAges (b + 16) c

现在我希望能够以以下形式插入一个人 Simon 作为特定人 Hans 的孩子

insertChildOf "Hans" simon:Person casperFamily:FamilyTree;;

因此,输入应该是父 namechild家谱。理想情况下,它应该返回一个修改后的家谱,即 FamilyTree 选项

我正在努力的是合并 validate 函数以确保它是合法的,以及一种将其正确插入子列表中的方法,如果插入 Person 已经是父级 - 也许作为一个单独的函数。

欢迎并非常感谢所有帮助 - 谢谢! :)

【问题讨论】:

  • 我猜如果名字匹配并且年龄无效它应该返回None,但是如果名字与家谱中的任何一个都不匹配怎么办?它应该返回未修改的树吗?你有没有想过这两种不同的情况?如果匹配多个名称怎么办?
  • 首先;非常感谢您的宝贵时间!在无法插入的情况下,返回值应为 None。也就是说,如果年龄不匹配,或者你找不到名字。暂时让我们说不会有重复的名字:p

标签: insert tree f# treenode


【解决方案1】:

在您发表评论后,下面的代码将按预期运行:

let insert pntName (Person(_, newPrsnYear, _) as newPrsn) (Person (n,y,ch)) =
    let rec ins n y = function
        | [] -> if y < newPrsnYear && n = pntName then Some [newPrsn] else None
        | (Person (name, year, childs) as person) :: bros ->
            let tryNxtBros() = Option.map (fun x -> person::x) (ins n y bros)
            if y < newPrsnYear && n = pntName then // father OK
                if newPrsnYear < year then // brother OK -> insert here
                    Some (newPrsn::person::bros)
                else tryNxtBros()
            else // keep looking, first into eldest child ...
                match ins name year childs with
                | Some i -> Some (Person (name, year, i) :: bros)
                | _      -> tryNxtBros() // ... then into other childs
    Option.map (fun x -> Person (n, y, x)) (ins n y ch)

在我之前的回答中,我一直避免使用 List 函数,因为我认为它们不适合树结构,除非树提供遍历。

在我使用列表函数(带有 lambda 和组合器)或纯递归的意义上,我可能有点纯粹,但总的来说,我不喜欢混合使用它们。

【讨论】:

  • 太棒了,古斯塔沃!谢谢
  • 它似乎将 newPerson 作为树中的最后一个人插入,不是吗?
  • @SimonEmil 我明白你的意思,是的,最大的子分支中有一个错误。现在应该没事了。
猜你喜欢
  • 1970-01-01
  • 2017-03-24
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多