【问题标题】:Find character in tree with SML使用 SML 在树中查找字符
【发布时间】:2020-07-09 23:17:25
【问题描述】:

我是 SML 的新手,并试图围绕函数式编程进行思考。我想要一个函数,它接受一个树 t 和一个字符 c,如果树包含该字符,则返回 true 或 false。

我要实现的算法是:

  1. 如果叶子为空返回false,

  2. 否则,如果字符在叶子中,则返回 true,

  3. 返回左树结果或右树结果

这是我的树数据类型

datatype 'a tree =
    Leaf of 'a
  | Node of 'a tree * 'a * 'a tree;

这就是函数

fun containsChar (Leaf t, c: char) = false 
  | containsChar (Node (left, t, right)) = 
    if t = c then true else false
  | containsChar (Node (left, t, right)) = (containsChar left) <> (containsChar right);

我收到Unbound value identifier "c". 这是为什么?

【问题讨论】:

    标签: algorithm functional-programming sml


    【解决方案1】:

    在该子句中没有所谓的“c”。在叶子的情况下有一个“c”,但这是一个完全不同的情况。在其他情况下,您忘记了该参数。
    (而if t = c then true else false 等价于t = c。)

    您在第二个和第三个子句中也有相同的模式,这是行不通的。

    您遇到的另一个问题是“叶子为空”规则——叶子不能为“空”。
    我怀疑这是让您误入歧途的原因,因为您的第一个子句的结果是 false,即使该论点显然是现有的叶子,而您的第二个子句显然不是叶子,但看起来像您的第二条规则。

    你的规则应该是这样的:

    一棵树包含一个字符当且仅当

    • 它是叶子中的值,或者
    • 它是节点中的值,或者
    • 它包含在节点的子树中。

    在 ML 中(删除对 char Tree 的限制,因为它看起来很随意),

    fun contains (Leaf t, c) = t = c 
      | contains (Node (left, t, right), c) = t = c
                                           orelse contains(left, c)
                                           orelse contains(right, c) 
    

    【讨论】:

    • 感谢您的 cmets,它们非常有帮助。我想我的困惑在于确定没有更多节点可以遍历的基本情况。在 Java 中,我们会说 if (node == null)。这在你的功能中是如何确定的?
    • @agomez 一棵树要么是一个节点,要么是一片叶子(这就是你的定义所说的)。这些是唯一的情况,当你到达叶子时,没有更多的节点可以遍历。在 SML 中事物不能是“无”。
    【解决方案2】:

    您可以再次将函数概括为

    fun any p Leaf = false
      | any p (Node (left, x, right)) =
          p x orelse any p left orelse any p right
    
    fun contains c t = any (fn x => c = x) t
    

    【讨论】:

      猜你喜欢
      • 2018-07-28
      • 2015-01-03
      • 2015-08-22
      • 2012-10-29
      • 2020-04-04
      • 2013-01-01
      • 2020-02-18
      • 1970-01-01
      • 2014-06-24
      相关资源
      最近更新 更多