【问题标题】:Checking whether a given value exists in a binary tree检查给定值是否存在于二叉树中
【发布时间】:2016-02-09 15:56:51
【问题描述】:

我是 SML 的新手。我正在尝试检查二叉树中是否存在给定值。下面是代码的sn-p。执行后它会给出

Warning : match nonexhaustive (n,Node (t1, j, t2)) => ...

我不明白为什么会这样显示。我想我已经涵盖了所有可能的情况。谁能给我提示或链接,这将有助于删除此警告。

datatype inttree = Empty | Node of inttree * int * inttree;

(*find(n,K) here n is the key that we have to find in inttree K*)
val rec find = fn(n, Node(t1,j,t2)) =>
    let 
        val t = Node(t1, j, t2)
        val compare = fn(i,j) => i = j
        val find' =
            fn (n,Empty) => false                (* if we have reached the empty node then we are not able to find the key therefore return false *)
             | (n,Node(t1,j,t2)) =>
               if compare(n,j)
               then true                         (* if value n and j are equal we have found the key n in the tree*)
               else find(n,t1) orelse find(n,t2) (* if the value is not equal check in left subtree if found return true else check in the right subtree*) 
    in
        find'(n,t)
    end;

【问题讨论】:

  • 你永远不会定义find (n,Empty) 我不太确定你在用所有这些匿名函数和compare 做什么。你让它变得比需要的复杂得多。
  • @John Coleman 如果 cmets 有帮助?请指导我如何使这不那么复杂。提前致谢

标签: sml smlnj


【解决方案1】:

鉴于您的数据类型声明,一个相当直接的递归方法是可能的。由于这似乎是家庭作业,我不想给出完整的解决方案,但这里有一个类似风格的函数:

fun allEven Empty = true
|   allEven (Node(t1,i,t2)) =
       if i mod 2 = 1 then false
       else allEven t1 andalso allEven t2;

此函数根据树中的所有整数是否为偶数返回真或假。它有一个基础案例

allEven Empty = true

(正确,因为在空树中没有奇数可作为反例)和递归情况

allEven (Node(t1,i,t2)) =
           if i mod 2 = 1 then false
           else allEven t1 andalso allEven t2;

如果节点处的整数是奇数,则返回 false -- 否则如果对两个分支的递归调用计算结果为 true,则返回 true。

典型运行:

- allEven (Node(Node(Empty,3,Empty),5,Node(Node(Empty,6,Empty),7,Empty)));
val it = false : bool
- allEven (Node(Node(Empty,4,Empty),2,Node(Node(Empty,6,Empty),8,Empty)));
val it = true : bool

你的函数应该有这么长并且遵循相同的基本递归模式。

【讨论】:

  • 不,这不是家庭作业,我正在学习它来教我的朋友。谢谢,真的很有帮助。
【解决方案2】:
  1. 除了val rec,您还可以写fun并在=的左侧指定参数。
  2. 辅助函数compare 在很大程度上是多余的。您不妨使用=。此外,在 ML 中称为比较函数的通常是返回类型 order 的函数,其值为 LESSEQUALSGREATER

    - ​Int.compare (3, 5);
    > val it = LESS : order
    
  3. 在编写if ... then true else ... 或返回类型bool 的类似语句时,您不妨只使用组合符orelseandalso。例如,您可以替换以下内容:

    if compare(n,j)
    then true
    else find(n,t1) orelse find(n,t2)
    

    与:

    n = j orelse find (n, t1) orelse find (n, t2)
    
  4. 就像内置函数 List.existsList.all 一样,将函数作为谓词并扫描列表以试图证明至少存在一个元素是正确的,或者它是正确的所有元素,你可以制作函数treeExiststreeForall

    datatype intTree = Empty | Node of inttree * int * inttree;
    
    fun treeExists f Empty = false
      | treeExists f (Node (leftTree, x, rightTree)) =
        f x orelse treeExists f leftTree orelse treeExists f rightTree
    
    fun treeForall f Empty = true
      | treeForall f (Node (leftTree, x, rightTree)) =
        f x andalso treeForall f leftTree andalso treeExists f rightTree
    

    使函数findallEven 现在变得更简单了:

    fun find (x, tree) = treeExists (fn y => x = y) tree
    fun allEven tree = treeForall (fn x => x mod 2 = 0) tree
    

    因为所有的递归都留给了新的库函数。

    以类似的方式,您可以制作treeMaptreeFold

    fun treeMap f Empty = Empty
      | treeMap f (Node (leftTree, x, rightTree)) = ...
    
    fun treeFold f e Empty = e
      | treeFold f e (Node (leftTree, x, rightTree)) = ...
    

    它们可用于查找树中最大的绝对值:

    fun maxAbsTree tree =
        treeFold Int.max 0 (treeMap Int.abs tree)
    

【讨论】:

  • 您的高阶树函数(treeExiststreeForall)很好,很好地说明了函数式编程。
  • @Simon Shine 感谢您的启发。你的方法一目了然,一目了然。非常感谢
猜你喜欢
  • 1970-01-01
  • 2015-04-23
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多