简体   繁体   中英

Assistance working with Binary Trees in SML

I'm new to SML and would like some assistance in using the following implementation of a binary tree.

datatype tree = NODE of int * tree * tree | LEAF of int;

I see that the tree is defined by either nodes which has two sub-trees or a LEAF with an integer.

How can I access the subtrees so that I can determine the maximum, the minimum, and if the element is present in the tree?

What is the process of accessing either the left and right sub-trees?

What is the process of accessing either the left and right sub-trees?

You use pattern matching:

fun goLeft (NODE (_, l, _)) = l
  | goLeft LEAF = raise Fail "Cannot go left here!"

fun goRight (NODE (_, _, r)) = r
  | goRight LEAF = raise Fail "Cannot go right here!"

How can I [...] determine the maximum, the minimum, and if the element is present in the tree?

You build recursive functions that pattern match on sub-trees.

For example, there is no invariant in a binary tree that says that the minimal element has a fixed, known location in the tree. But this invariant is present in a binary search tree, in which all elements in every left sub-tree (including the root) are made sure to be less than or equal to all the elements of their right sub-trees.

The tree

    5
   / \
  3   8
 /   / \
2   7   9

qualifies as a binary search tree because this invariant holds.

Finding the minimal element in such a tree means recursing in such a way that you always pick the left sub-tree until there is no left sub-tree, in which case you have found the minimum. How do you know when to stop recursion?

fun goLeeeft (NODE (_, l, _)) = goLeeeft l
  | goLeeeft LEAF = "I've gone all the way left, but I have nothing to show for it."

fun minimum (NODE (x, l, r)) = (* is this the last non-leaf node? *)
  | minimum LEAF = raise Empty (* whoops, we recursed too far! *)

When you pattern match one level deep, that is, on NODE (x, l, r) , you only know that this is a non-leaf node, but you don't know the exact value located in the node, x , and you don't know anything about the sub-structure of this node's left and right sub-trees.

You could go two ways here: Either make a helper function that tells you when to stop recursing, or pattern match one level deeper into l . Here are two examples of that; they perform the same thing:

(* Using a helper function *)
fun isLeaf (NODE (_, _, _)) = false
  | isLeaf LEAF = true

fun minimum (NODE (x, l, _)) =
      if isLeaf l
      then x
      else minimum l
  | minimum LEAF = raise Empty

(* Using direct pattern matching *)
fun minimum (NODE (x, LEAF, _)) = x
  | minimum (NODE (x, l, _)) = minimum l
  | minimum LEAF = raise Empty

Now maximum writes itself.

As a curiosity, you can define generic recursion schemes such as folding on trees:Sml folding a tree

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM