OmegaTwig
OmegaTwig

Reputation: 253

Find the deepest element of a Binary Tree in SML

This is a homework question.

My question is simple: Write a function btree_deepest of type 'a btree -> 'a list that returns the list of the deepest elements of the tree. If the tree is empty, then deepest should return []. If there are multiple elements of the input tree at the same maximal depth, then deepest should return a list containing those deepest elements, ordered according to a preorder traversal. Your function must use the provided btree_reduce function and must not be recursive.

Here is my code:

(* Binary tree datatype. *)
datatype 'a btree = Leaf | Node of 'a btree * 'a * 'a btree

(* A reduction function. *)
(* btree_reduce : ('b * 'a * 'b -> 'b) -> 'b -> 'a tree -> 'b) *)
fun btree_reduce f b bt =
   case bt of
   Leaf => b
   | Node (l, x, r) => f (btree_reduce f b l, x, btree_reduce f b r)

(* btree_size : 'a btree -> int *)
fun btree_size bt =
    btree_reduce (fn(x,a,y) => x+a+y) 1 bt

(* btree_height : 'a btree -> int *)
fun btree_height bt =
    btree_reduce (fn(l,n,r) => Int.max(l, r)+1) 0 bt

I know that I have to create a function to pass to btree_reduce to build the list of deepest elements and that is where I am faltering.

If I were allowed to use recursion then I would just compare the heights of the left and right node then recurse on whichever branch was higher (or recurse on both if they were the same height) then return the current element when the height is zero and throw these elements into a list.

I think I just need a push in the right direction to get started...

Thanks!

Update:

Here is an attempt at a solution that doesn't compile:

fun btree_deepest bt =
let
val (returnMe, height) = btree_reduce (fn((left_ele, left_dep),n,(right_ele, right_dep)) => 
    if left_dep = right_dep 
        then 
            if left_dep = 0 
                then ([n], 1) 
                else ([left_ele::right_ele], left_dep + 1)
        else 
            if left_dep > right_dep
                then (left_ele, left_dep+1) 
                else (right_ele, right_dep+1)
    ) 
    ([], 0) bt
in  
    returnMe
end

Upvotes: 1

Views: 1405

Answers (2)

Matt Alioto
Matt Alioto

Reputation: 423

Took a look at your code; it looks like there is some confusion based on whether X_ele are single elements or lists, which causes the type error. Try using the "@" operator in your first 'else' branch above:

        if left_dep = 0 
            then ([n], 1) 
            else (left_ele @ right_ele, left_dep + 1)

Upvotes: 1

waldrumpus
waldrumpus

Reputation: 2590

In order to get the elements of maximum depth, you will need to keep track of two things simultaneously for every subtree visited by btree_reduce: The maximum depth of that subtree, and the elements found at that depth. Wrap this information up in some data structure, and you have your type 'b (according to btree_reduce's signature).

Now, when you need to combine two subtree results in the function you provide to btree_reduce, you have three possible cases: "Left" sub-result is "deeper", "less deep", or "of equal depth" to the "right" sub-result. Remember that the sub-result represent the depths and node values of the deepest nodes in each subtree, and think about how to combine them to gain the depth and the values of the deepest nodes for the current tree.

If you need more pointers, I have an implementation of btree_deepest ready which I'm just itching to share; I've not posted it yet since you specifically (and honorably) asked for hints, not the solution.

Upvotes: 3

Related Questions