检查二叉树中是否存在给定值

时间:2016-02-09 00:26:17

标签: sml smlnj

我是SML的新手。我试图检查二进制树中是否存在给定值。下面是代码的片段。执行后,它给出了

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;

2 个答案:

答案 0 :(得分:1)

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

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

此函数返回true或false,具体取决于树中的所有整数是否均匀。它有一个基础案例

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

你的功能应该是这么长,并遵循相同的基本递归模式。

答案 1 :(得分:1)

  1. val rec外,您还可以撰写fun并在=的左侧指定参数。
  2. 辅助函数compare在很大程度上是多余的。您也可以使用=。此外,人们称之为ML中的比较函数通常是返回 order 类型的函数,其值为LESSEQUALSGREATER

    - ​Int.compare (3, 5);
    > val it = LESS : order
    
  3. 在编写返回 bool 类型的if ... then true else ...或类似语句时,您也可以使用组合器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)