OCaml Heap Missing Nodes - ocaml

I have defined a type heap:
type 'a heap =
| Node of int * int * 'a heap * 'a heap
| Leaf;;
And the following functions:
let rank = function Leaf -> 0 | Node (r,_,_,_) -> r;;
let makeNode x a b =
if rank a>= rank b then Node(rank b+1,x,a,b)
else Node (rank a+1,x,a,b);;
let rec meld = function
|h,Leaf | Leaf,h -> h
| (Node(f,x,a1,b1)as h1),(Node(g,y,a2,b2)as h2) -> if x >= y then makeNode x a1 (meld (b1, h2))
else makeNode y a2 (meld (h1, b2));;
let insert h x = meld ((Node(1,x,Leaf,Leaf)), h);;
However, when I insert a second node into the heap, the root disappears. How can I fix this:
let makeheap x = Node(1,x,Leaf,Leaf);;
let myheap = makeheap 5;;
insert myheap 7;;
insert myheap 8;;
insert myheap 3;;
results in the following output:
val myheap : 'a heap = Node(1,5,Leaf,Leaf)
'a heap = Node(1,7,Leaf,Node(1,5,Leaf,Leaf))
'a heap = Node (1,8,Leaf,Node(1,5,Leaf,Leaf))
'a heap = Node(1,5,Leaf,Node(1,3,Leaf,Leaf))

You're calling insert as if it's an imperative function. I.e., as if it's going to change some state. But your data structure is immutable. You have to think of insert as returning the new state.
You should read up on pure functional programming before going too much farther, I suspect.
The first few chapters of Okasaki's Purely Functional Data Structures explain things very well.
The answer to your immediate question is something like this:
# insert (insert myheap 7) 8;;
- : 'a heap = Node (1, 8, Leaf, Node (1, 7, Leaf, Node (1, 5, Leaf, Leaf)))

Related

verifying size of binary trees?

I have a datatype in this way
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
so an example for correct tree would be:
val tree1 =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
3,2,
Node(Leaf 27, 1, 1, Leaf 96))
and an example for violating tree would be
val tree1false =
Node(Node(Node(Leaf 47, 1, 1, Leaf 38),
2,1,
Leaf 55),
4,2,
Node(Leaf 27, 1, 1, Leaf 96))
How can I write a predicate test such that
- test tree1;
val it = true : bool
- test tree1false;
val it = false : bool
This is a recursive problem. Before solving recursive problems on trees, it is a good idea to have a firm grasp on recursion on lists. You could say that trees are generalisations of lists, or that lists are special-cases of trees: lists have one tail, trees can have any number of tails depending on the type of tree. So here is how you could reconstruct and solve the problem using lists:
If, instead of the typical list definition, you have a list that also memoizes its own length:
(* datatype 'a list = [] | :: of 'a * 'a list *)
datatype 'a lenlist = Nil | Cons of int * 'a * 'a lenlist
Then you can test that the stored length is in accordance with the actual number of values.
I'll start by creating a function that counts to illustrate the part of the function that performs recursion:
(* For regular built-in lists *)
fun count0 [] = 0
| count0 (x::xs) = 1 + count0 xs
(* Counting the memoized list type disregarding the n *)
fun count1 Nil = 0
| count1 (Cons (n, x, xs)) = 1 + count1 xs
The next part is that I'd like, in each recursive step, to test that the stored number n is also in accordance with the actual counting. What is the return type of this function? Well, the test function that you want should be 'a lenlist -> bool and the count function that I made is 'a lenlist -> int.
I will suggest that you make a testcount that kinda does both. But you can do so in many ways, e.g. by giving it "extra arguments", or by giving it "extra return values". I will demonstrate both, just to show that sometimes one is better than the other and experience will tell you which.
Here is a val testcount1 : 'a lenlist -> bool * int function:
fun testcount1 Nil = (true, 0)
| testcount1 (Cons (n, x, xs)) =
let val (good_so_far, m) = testcount1 xs
val still_good = good_so_far andalso n = m + 1
in (still_good, m + 1)
end
val goodList = Cons (4, #"c", Cons (3, #"o", Cons (2, #"o", Cons (1, #"l", Nil))))
val badList = Cons (3, #"d", Cons (2, #"e", Cons (1, #"r", Cons (0, #"p", Nil))))
Testing this,
- testcount1 goodList;
> val it = (true, 4) : bool * int
- testcount1 badList;
> val it = (false, 4) : bool * int
This shows that testcount1 returns whether the numbers add up and the list's actual length, which was necessary during recursion to test that the numbers add up in each step, but in the end is no longer necessary. You could wrap this testcount function up in a simpler test function that only cares about the bool:
fun test xs = #1 (testcount1 xs)
Here is another way to go about: There is something not so satisfying with the way testcount1 recurses. It keeps calculating the m + 1s even though it is able to determine that a list (e.g. at Cons (0, #"p", Nil)) is broken.
Here is an alternate val testcount2 : 'a lenlist * int -> bool that stores a number in an extra argument instead:
fun testcount2 (Nil, 0) = true
| testcount2 (Nil, _) = false
| testcount2 (Cons (n, x, xs), m) =
n = m andalso testcount2 (xs, m - 1)
This seems a lot neater to me: The function is tail-recursive, and it stops immediately when it senses that something is fishy. So it doesn't need to traverse the entire list if it's broken at the head. The downside is that it needs to know the length, which we don't know yet. But we can compensate by assuming that whatever is advertised is correct until it's clearly the case, or not.
Testing this function, you need to not only give it a goodList or a badList but also an m:
- testcount2 (goodList, 4);
> val it = true : bool
- testcount2 (badList, 4);
> val it = false : bool
- testcount2 (badList, 3);
> val it = false : bool
It's important that this function doesn't just compare n = m, since in badList, that'd result in agreeing that badList is 3 elements long, since n = m is true for each iteration in all Cons cases. This is helped in the two Nil cases that require us to have reached 0 and not e.g. ~1 as is the case for badList.
This function can also be wrapped inside test to hide the fact that we feed it an extra argument derived from the 'a lenlist itself:
fun size Nil = 0
| size (Cons (n, _, _)) = n
fun test xs = testcount2 (xs, size xs)
Some morals so far:
Sometimes it is necessary to create helper functions to solve your initial problem.
Those helper functions are not restricted to have the same type signature as the function you deliver (whether this is for an exercise in school, or for an external API/library).
Sometimes it helps to extend the type that your function returns.
Sometimes it helps to extend the arguments of your functions.
Just because your task is "Write a function foo -> bar", this does not mean that you cannot create this by composing functions that return a great deal more or less than foo or bar.
Now, for some hints for solving this on binary trees:
Repeating the data type,
datatype 'a bin_tree =
Leaf of 'a
| Node of 'a bin_tree (* left tree *)
* int (* size of left tree *)
* int (* size of right tree *)
* 'a bin_tree (* right tree *)
You can start by constructing a skeleton for your function based on the ideas above:
fun testcount3 (Leaf x, ...) = ...
| testcount3 (Leaf x, ...) = ...
| testcount3 (Node (left, leftC, rightC, right), ...) = ...
I've embedded som hints here:
Your solution should probably contain pattern matches against Leaf x and Node (left, leftC, rightC, right). And given the "extra argument" type of solution (which at least proved nice for lists, but we'll see) needed two Leaf x cases. Why was that?
If, in the case of lists, the "extra argument" m represents the expected length of the list, then what would an "extra argument" represent in the case of trees? You can't say "it's the length of the list", since it's a tree. How do you capture the part where a tree branches?
If this is still too difficult, consider solving the problem for lists without copy-pasting. That is, you're allowed to look at the solutions in this answer (but try not to), but you're not allowed to copy-paste code. You have to type it if you want to copy it.
As a start, try to define the helper function size that was used to produce test from testcount2, but for trees. So maybe call it sizeTree to avoid the name overlap, but other than that, try and make it resemble. Here's a skeleton:
fun sizeTree (Leaf x) = ...
| sizeTree (Node (left, leftC, rightC, right)) = ...
Sticking testcount3 and sizeTree together, once written, should be easy as tau.

How to pass value of recursive function for tree

I have recursive function, for course the branch of the tree
type tree = Node of bool ref * (char * tree) list ref
type cours= tree ->char list -> char list* char list * tree
let cours t word=
let rec cours_tree t word l1 l2=match t,word with
| Noeud(r,n),[] -> Noud (r,n), l1 , l2
| Noeud (r,n),x::h when (List.mem_assoc x !n) ->
x::l1,cours_tree (List.assoc x !n) h l1 l2
| Noeud (r,{content=(c,b)::n),x::h ->
x::l2,cours_tree (List.assoc x b) h l1 l2
in
cours_tree t word [] []
I would expect this to Browse a tree from a given list of characters, and return the subtree reached, the character list and the list of those who could not be reached;
But I'm getting an error:
Error: This expression has type char list * 'a
but an expression was expected of type 'a
The type variable 'a occurs inside char list * 'a#
I dont know where is my problem.
There are many problems:
Noud and Noeud are undefined constructors.
Unmatched { when you attempt to pattern match on the ref.
First match case returns tree * list * list but the other cases
return infinite types.
Incorrect ref pattern matching syntax. content should be contents.
Type error in the second List.assoc. b is a tree but an expression of type (char * 'a) list is expected.
The following code fixes the problems and while compile, but will not run correctly as the problem description you gave is not complete:
type tree = Node of bool ref * (char * tree) list ref
type cours = tree -> char list -> char list * char list * tree
let cours t word =
let rec cours_tree t word l1 l2 =
match t, word with
| Node (r, n), [] -> Node (r, n), l1, l2
| Node (r, n), x::h when List.mem_assoc x !n ->
let t', l1', l2' = cours_tree (List.assoc x !n) h l1 l2 in
t', x::l1', l2'
| Node (r, {contents = (c, b)::n}), x::h ->
let t', l1', l2' = cours_tree (List.assoc x n) h l1 l2 in
t', l1', x::l2'
in cours_tree t word [] []

How can I create a ternary tree in SMLNJ?

Right now I have a binary tree modeled in SMLNJ however I want to change this model to where there is a tree inside of tree inside of tree. (Ternary Tree)
If you begin with the root of a binary tree.
Binode with an (id1*(binode)) ß- a binary tree
Then if that “binode” is located as part of a tuple: 2Dbinode
That tuple has an identifier and that binode with is the root of the binode tree.
2Dbinode (id2* (binode) *2Dbinode)
Each of those in turn are part of a 3Dbinode which consists of:
3Dbinode(id3 * (2Dbinode) * 3Dbinode)
For ex. 3Dbinode(id3 * (2Dbinode) * 3Dbinode) the root 3Dbinode might contain the following data:
(25, (7, (11)))
And by adding the nodes (25, (7, (22)))
(25, (10, (4))), (30, (7, (22)))
3DBinary Tree Model
Here is SMLNJ code for the 2D binary tree I am modifying.
datatype btree = Empty | Node of int * btree * btree;
fun AddNode (i:int, Empty) = Node(i, Empty, Empty) |
AddNode(i:int, Node(j, left, right)) =
if i = j then Node(i, left, right)
else if i < j then Node(j, AddNode(i, left), right)
else Node(j, left, AddNode(i, right));
fun printInorder Empty = () |
printInorder (Node(i,left,right)) =
(printInorder left; print(Int.toString i ^ " "); printInorder right);
val x : btree = AddNode(50, Empty);
val x : btree = AddNode(75, x);
val x : btree = AddNode(25, x);
val x : btree = AddNode(72, x);
val x : btree = AddNode(20, x);
val x : btree = AddNode(100, x);
val x : btree = AddNode(3, x);
val x : btree = AddNode(36, x);
val x : btree = AddNode(17, x);
val x : btree = AddNode(87, x);
printInorder(x);
I need to populate the data structure with N randomized (3Dnodes):
How can I implement these functions?
Search for a specific node displaying the path to the node ex: (25, 10, 4) the display would be
(25)
(25, 7)
(25, 10)
(25, 10,4)
If the user searches for a node that does not exist:
(30, (7, (30))) then the path displayed would be
(25)
(30)
(30,7)
(30, 7, 30) NOT FOUND
If the user wishes to ADD a node at any level they should be prompted to enter the 3 digit code for that node; Again the path should be displayed.
EX: ADD (30, 11, 5) then the display would be
(25)
(30)
(30, 7)
(30, 11) created
(30, 11, 5) created
Print out the contents of the 3dbinode tree as a sequence of (A,B,C)
DELETE a node
Delete a node: EX: DEL (30, 7, _)
Then the result would be
- (30, 7, 22) deleted
- (30, 7, 0) created
Ternary tree?
Edit 2: After you reviewed your question, it still seems unclear how you wish to navigate this ternary tree when searching it. A binary search tree divides its elements left and right depending on which one is greater. You have described no similar criterion: When should your functions use the first, second and third branch?
Edit 3: I've provided the function pathExists that works on ternary trees, but AddNode is still missing as you have not provided any insight into the questions that I've highlighted with bold. If your tree really does serve the purpose of containing points in a 3-dimensional space, it does sound like you want a k-d tree, as I suggested once. I've also partially provided the function make3DTree under the assumption that a k-d tree is what you're looking for.
Until I saw the drawing you made of a ternary tree (or generally an n-ary tree), I could not understand your question. A ternary tree simply has (up to) three child nodes at each level instead of the binary tree's two.
The wording "tree inside of a tree inside of a tree" means something different than the branching factor (2, 3, n). Exactly how you turn the triples (25, 7, 11), (25, 7, 22), (25, 10, 4), and (30, 7, 22) into your ternary tree is still a little puzzling to me. It seems that the bottom nodes only have two empty leaves. I will interpret this as if there were a third empty arrow in the middle.
Your AddNode function constructs binary search trees where the smaller elements go to the left, and the larger elements to the right. But how, then, do you wish to use a third branch?
Compare the following generic / integer-specific binary tree datatype definitions,
datatype 'a btree = BTreeEmpty | BTreeNode of 'a * 'a btree * 'a btree
datatype int_btree = BTreeEmpty | BtreeNode of 'a * int_btree * int_btree
with the ones for ternary trees,
datatype 'a ttree = TTreeEmpty | TTreeNode of 'a * 'a ttree * 'a ttree * 'a ttree
datatype int_ttree = TTreeEmpty | TtreeNode of 'a * int_ttree * int_ttree * int_ttree
or even ones that support variable branching in each node,
datatype 'a tree = TreeEmpty | TreeNode of 'a * 'a tree list
datatype int_tree = TreeEmpty | TreeNode of int * int_tree list
Creating the ternary tree you depicted,
val treeModel =
let val t = TTreeNode
val e = TTreeEmpty
in
t (25,
e,
t (7,
e,
t (11, e, e, e),
t (10,
e,
t (4, e, e, e),
e
)
),
t (30,
e,
t (7,
e,
t (22, e, e, e),
e
),
e)
)
end
although it would probably be more convenient with a function like AddNode, only you need to specify a consistent way for elements to be added to this kind of tree. How does the binary search tree logic translate to ternary trees?
Determining if a path exists in a ternary tree
You can determine if a path to a node exists. Since a tree can have any depth, a path can have any length and should be represented with a list. The path [25, 7, 10, 4] exists in your ternary tree, for example.
fun pathExists [] _ = true (* the empty path is trivially found *)
| pathExists _ TTreeEmpty = false (* no non-empty path goes through an empty tree *)
| pathExists (x::xs) (TTreeNode (y, subtree1, subtree2, subtree3)) =
x = y andalso
(pathExists xs subtree1 orelse
pathExists xs subtree2 orelse
pathExists xs subtree3)
Testing this function with treeModel above:
- pathExists [25, 7, 10, 4] treeModel;
> val it = true : bool
- pathExists [25, 30, 7, 22] treeModel;
> val it = true : bool
- pathExists [25, 7, 11, 9] treeModel;
> val it = false : bool
- pathExists [25, 7, 9] treeModel;
> val it = false : bool
Inserting a point in a ternary tree [???]
A template for this function could be
fun AddNode (x, TTreeEmpty) = TTreeNode (x, TTreeEmpty, TTreeEmpty, TTreeEmpty)
| AddNode (x, TTreeNode (y, subtree1, subtree2, subtree3))) = ???
but if x <> y, which of the three subtrees should it try to add x to?
K-d tree?
Edit 1: After having answered, I realize that perhaps you are looking for a k-d tree? A k-d tree can store k-dimensional vectors, using only binary trees, in a way that allows efficient, locality-specific lookups.
The great trick here is to say that the 1st level of the tree divides the space into two halves on the X-axis, the 2nd level of the tree divides the left/right halves into halves on the Y-axis, the 3rd level of the tree divides the left/right halves into halves on the Z-axis, the 4th level on the X-axis again, the 5th level on the Y-axis again, and so on.
Here is an initial translation of that pseudocode for k = 3 into Standard ML:
(* 'byDimension dim (p1, p2)' determines if p1 is greater than p2 in dimension dim. *)
fun byDimension 0 ((x1,_,_), (x2,_,_)) = x1 > x2
| byDimension 1 ((_,y1,_), (_,y2,_)) = y1 > y2
| byDimension 2 ((_,_,z1), (_,_,z2)) = z1 > z2
| byDimension d _ _ = raise Fail ("Invalid dimension " ^ Int.toString d)
(* split points into two halves and isolate the middle element *)
fun splitAt dim points = ...
(* The number of dimensions, matching the arity of the point tuples below *)
val k = 3
fun make3DTree ([], _) = BTreeEmpty
| make3DTree (points, depth) =
let val axis = depth mod k
val len = List.length points
val points_sorted = ListMergeSort.sort (byDimension axis) points
val (points_left, median, points_right) = splitAt len points_sorted
in BTreeNode (median,
make3DTree (points_left, depth+1),
make3DTree (points_right, depth+1))
end
One optimization could be to reduce the constant re-sorting.
Adding a single 3D point to this tree is well-defined, but does not guarantee that the tree is particularly balanced:
(* get the (n mod 3)-th value of a 3-tuple. *)
fun getDimValue (n, (x,y,z)) =
let val m = n mod k
in if m = 0 then x else
if m = 1 then y else
if m = 2 then z else
raise Fail ("Invalid dimension " ^ Int.toString n)
end
(* the smallest tree that contains a k-dimensional point
* has depth k-1 (because of 0-indexing). *)
fun deepEnough depth = depth >= k-1
fun insertNode (point, BTreeEmpty, depth) =
let val v1 = getDimValue (depth, point)
val v2 = getDimValue (depth+1, point)
val (left, right) =
if deepEnough depth
then (BTreeEmpty, BTreeEmpty)
else if v1 > v2
then (insertNode (point, BTreeEmpty, depth+1), BTreeEmpty)
else (BTreeEmpty, insertNode (point, BTreeEmpty, depth+1))
in BTreeNode (v1, left, right)
end
| insertNode (point, BTreeNode (v1, left, right), depth) =
let val v2 = getDimValue (depth, point)
in if v1 > v2
then BTreeNode (v1, insertNode (point, left, depth+1), right)
else BTreeNode (v1, left, insertNode (point, right, depth+1))
end
Determining if a point exists in this tree can be achieved by performing a nearest-neighbor search, which is slightly less trivial to implement.

Creating a doubly linked list from a list in OCaml

I am often told that using the Lazy module in OCaml, one can do everything you can do in a lazy language such as Haskell. To test this claim, I'm trying to write a function that converts a regular list into a static doubly linked list in ocaml.
type 'a dlist = Dnil | Dnode of 'a dlist * 'a * 'a dlist
Given this type I can create several static doubly linked lists by hand:
let rec l1 = Dnode (Dnil,1,l2)
and l2 = Dnode (l1,2,l3)
and l3 = Dnode (l2,3,Dnil)
but I'd like to write a function of type 'a list -> 'a dlist that given any list builds a static doubly linked list in OCaml. For example given [1;2;3] it should output something equivalent to l1 above.
The algorithm is pretty straightforward to write in Haskell:
data DList a = Dnil | Dnode (DList a) a (DList a)
toDList :: [a] -> DList a
toDList l = go Dnil l
where
go _ [] = Dnil
go h (x:xs) = let r = Dnode h x (go r xs) in r
but I haven't been able to figure out where to place calls to lazy to get this to compile in OCaml.
If you build your linked list in right-to-left order (as for normal lists), then the left element of every node will only be built after that node itself is built. You need to represent this by making the left element lazy, which means "this value will be constructed later" :
type 'a dlist =
| Dnil
| Dnode of 'a dlist Lazy.t * 'a * 'a dlist
Once you have this, construct every node as a lazy value using a recursive definition which passes the lazy (still unconstructed) node to the function call that builds the next node (so that it has access to the previous node). It's actually simpler than it looks :
let dlist_of_list list =
let rec aux prev = function
| [] -> Dnil
| h :: t -> let rec node = lazy (Dnode (prev, h, aux node t)) in
Lazy.force node
in
aux (Lazy.lazy_from_val Dnil) list
You can only build a cyclic immutable strict data structure of a shape that's determined at compile time. I'm not going to define or prove this formally, but intuitively speaking, once the data structure is created, its shape isn't going to change (because it's immutable). So you can't add to a cycle. And if you create any element of the cycle, you need to create all the other elements of the cycle at the same time, because you can't have any dangling pointer.
Ocaml can do what Haskell can do, but you do have to get the Lazy module involved! Unlike Haskell's, ML's data structures are strict unless otherwise specified. A lazy data structure has pieces of type 'a Lazy.t. (ML's typing is more precise than Haskell on that particular issue.) Lazy data structures allow cycles to be built by having provisionally-dangling pointers (whose linked values are automatically created when the pointer is first dereferenced).
type 'a lazy_dlist_value =
| Dnil
| Dnode of 'a lazy_dlist_value * 'a * 'a lazy_dlist_value
and 'a lazy_dlist = 'a lazy_dlist_value Lazy.t
Another common way to have cyclic data structures is to use mutable nodes. (In fact, die-hard proponents of strict programming might see lazy data structures as a special case of mutable data structures that doesn't break referential transparency too much.)
type 'a mutable_dlist_value =
| Dnil
| Dnode of 'a mutable_dlist_value * 'a * 'a mutable_dlist_value
and 'a mutable_dlist = 'a mutable_dlist_value ref
Cyclic data structures are mostly useful when they involve at least one mutable component, one function (closure), or sometimes modules. But there'd be no reason for the compiler to enforce that — cyclic strict immutable first-order data structures are just a special case which can occasionally be useful.
type 'a dlist = Dnil | Dnode of 'a dlist Lazy.t * 'a * 'a dlist Lazy.t
let rec of_list list = match list with
[] -> Dnil
| x :: [] ->
let rec single () = Dnode (lazy (single ()), x, lazy (single ()))
in single ()
| x :: y -> Dnode (
lazy (
of_list (match List.rev list with
[] | _ :: [] -> assert false
| x :: y -> x :: List.rev y
)
),
x,
lazy (
of_list (match list with
[] | _ :: [] -> assert false
| x :: y -> y # x :: []
)
)
)
let middle dlist = match dlist with
Dnil -> raise (Failure "middle")
| Dnode (_, x, _) -> x
let left dlist = match dlist with
Dnil -> raise (Failure "left")
| Dnode (x, _, _) -> Lazy.force x
let right dlist = match dlist with
Dnil -> raise (Failure "right")
| Dnode (_, _, x) -> Lazy.force x

Filling a normal binary tree in ML with values

Where let's say:
datatype bin_tree = Empty |
Node of value * bin_tree * bin_tree
How would I go about filling a binary tree (not a binary search tree where left is smaller than root and right bigger). Just values from a list inserted at each node in a binary tree.
You use the value constructors you've declared.
If we assume for a moment that value is int instead, then we for instance have that the tree
1
/ \
2 4
/
3
is represented by:
Node (1,
Node (2,
Node (3, Empty, Empty),
Empty
),
Node (4, Empty, Empty)
)
Or, equivalently, on one line:
Node (1, Node (2, Node (3, Empty, Empty), Empty), Node (4, Empty, Empty))
It's not really possible to help you, without knowing more about how you wan't your tree constructed from a given list. However here is an example that creates a balanced tree. It takes the first element and uses it as the node value, and then it splits the rest of the list into two sub lists of equal size (if possible), by taking all "even" element in the "left" list and all "odd" elements in the "right" list:
datatype 'a bin_tree = Empty
| Node of 'a * 'a bin_tree * 'a bin_tree
fun list_split xs =
let
fun loop [] (left, right) = (rev left, rev right)
| loop (x::y::xs) (left, right) = loop xs (x :: left, y :: right)
| loop (x :: xs) (left, right) = loop xs (x :: left, right)
in
loop xs ([], [])
end
fun built_tree [] = Empty
| built_tree (x :: xs) =
let
val (left, right) = list_split xs
val left_tree = built_tree left
val right_tree = built_tree right
in
Node (x, left_tree, right_tree)
end
The result:
- built_tree [1,2,3,4,5,6,7,8,9];
val it =
Node
(1,Node (2,Node (4,Node (8,Empty,Empty),Empty),Node (6,Empty,Empty)),
Node (3,Node (5,Node (9,Empty,Empty),Empty),Node (7,Empty,Empty)))
: int bin_tree
Here is an answer to the same question done in Java. This will probably help a good bit :).