How to write iterative inorder traversal for BST in OCaml - ocaml

It is easy enough to write recursive inorder traversal in OCaml, but how to write iterative one? with for loop or while?

Asking for someone to write something without recursive calls is stupid, but I'll still do it because it's an interesting exercise. Going from recursive to iterative is always the same process.
type tree = Leaf | Node of int * tree * tree
let rec in_order = function
| Leaf -> []
| Node(i,l,r) -> in_order l # (i :: in_order r);;
Alright, now we have our recursive function. The first step is to transform it to tail recursive. This is actually the hardest step since it requires a real logical and algorithmic change.
We are going to add a new parameter to the function that is going to contain the result of the computation :
let rec ino res = function
| Leaf -> ()
| Node(i,l,r) ->
begin
ino res r ;
res := i :: !res ;
ino res l
end
At the end, the result is !res.
Now that we have this, removing the recursive call is very easy, we just have to think about what does the compiler does when he has a recursive call. Well, it just does a while loop, after putting the parameters of the function and the next work to do in a stack. Let's just do it.
open Stack
type work = Value of int | NextNode of tree ref
let ino t : int list =
let res = ref [] in
let stack = Stack.create () in
push (NextNode (ref t)) stack;
try
while true do
let current = pop stack in
match current with
Value i -> res := i :: !res
| NextNode n ->
begin
match !n with
Leaf -> ()
| Node(i,l,r) ->
begin
push (NextNode (ref l)) stack;
push (Value i) stack;
push (NextNode (ref r)) stack
end
end
done;
assert false
with
| Empty -> !res
Here we just remember the next thing to do. We know that when we reach a node we have to treat its right child, then the value of the node, then its left child, so we just put all this in the stack (in reverse order of course), and we keep going to the next element of the stack. When the stack is empty, we have visited the whole tree, and we can return.
I hope that this post manages to convince some people of the power of recursion over iterative programming. 3 lines Vs 26 lines. QED.

Here's another take on iterative in-order traversals:
type 'a node = {mutable data: 'a;
mutable left : 'a node option;
mutable right: 'a node option; }
let new_node data = {data; left = None; right = None;}
let insert tree new_data =
let module Wrapper = struct exception Stop_loop end in
let iter = ref tree in
try
while true do
if new_data < !iter.data
then match !iter.left with
| None ->
!iter.left <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some left_tree -> iter := left_tree
else if new_data > !iter.data
then match !iter.right with
| None ->
!iter.right <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some right_tree -> iter := right_tree
done
with Wrapper.Stop_loop -> ()
let in_order_traversal tree =
let module W = struct exception Stop_loop end in
let visited_stack = Stack.create () in
let iter_node = ref (Some tree) in
try while true do
(* Inner loop, we keep trying to go left *)
(try while true do
match !iter_node with
| None -> raise W.Stop_loop
| Some left ->
Stack.push left visited_stack;
iter_node := left.left
done;
with W.Stop_loop -> ());
(* If we have no more to process in the stack, then we're
done *)
if Stack.length visited_stack = 0
then raise W.Stop_loop
else
(* Here we're forced to start moving rightward *)
let temp = Stack.pop visited_stack in
Printf.sprintf "%s " temp.data |> print_string;
iter_node := temp.right
done
with W.Stop_loop -> ()
let () =
let root = new_node "F" in
["B";"G";"A";"D";"I";"C";"E";"H"] |> List.iter (insert root);
in_order_traversal root;
print_newline ();

Related

Ocaml and return type (graph theory)

I'm just a begginer in Ocaml, and I wanted to study the graph theory, but with implementations in Ocaml. And I've got a trouble to do something : I just wanted to list the connected components of a graph by using a Depth first search. So, I did :
#open "stack" ;;
let non_empty pile =
try push (pop pile) pile ; true with Empty -> false ;;
let connected_comp g =
let already_seen = make_vect (vect_length g) false in
let comp = [] in
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
let rec head_list l = match l with
| [] -> failwith "Empty list"
| p::q -> p
in
let rec aux comp t = match t with
| t when t = vect_length g -> comp
| t when already_seen.(t) = true -> aux comp (t+1)
| t -> aux ((dfs t [])::comp) (t+1) (* we want that dfs t [] return the list lst modified *)
in aux comp 0;;
And I obtain :
> | t -> (dfs t [])::comp ; aux comp (t+1) (* we want that dfs t [] return the list lst modified *)
> ^^^^^^^^^^^^^^^^
Warning : this expression is of type unit list,
but is used with the type unit.
connected_comp : int list vect -> unit list = <fun>
- : unit list = []
- : unit = ()
Of course, I'm not surprised. But what I want to do is that the function dfs return the list sent on argument (the lst list) but modified, and here it's not the case as the function is of type unit, cause it return nothing. But in Ocaml, as the language is made for returning the last expression I think, I don't know how to do. I could as well use recursive algorithm for the dfs function, as, through filtering, it would permit me to return the list, but I just wanted to learn about Ocaml, and so modified (even if it's not optimal) my algorithm.
Someone could help me, please ?
Edit : As we ask me, I will try to reduce my code and get to the point. So, I have the function dfs which correspond to a Depth first search (for a graph)
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
(alreadyseen is a vector of boolean, defined previously)
And my only problem is that I want that the function return the list lst modified (in the loop while), when, at this point, it's a unit function.
I tried to define lst as a reference, but then I don't know how to return it...
I hope it's more clear, I'm not familiar with all of this at the moment...
Thank you !
Here is a degraded version of your code that demonstrate one way to do what you want.
let non_empty _ = false
let dfs s lst =
let local_lst = ref lst in
while non_empty () do
(*do stuff here*)
let s = 1 in
local_lst := s::!local_lst;
(*do stuff here*)
done;
!local_lst
I first initialize a local mutable value local_lst to the list lst given as an argument. I then update this value in the while loop. And finally I return the value stored in local_lst.

Insert implementation for a trie in Ocaml

I don't have any idea on how to change the code for my add function.
type trie = Node of bool * (char * trie) list
let explode word =
let rec explode' i acc =
if i < 0 then acc else explode' (i-1) (word.[i] :: acc)
in explode' (String.length word - 1) []
let rec exists w tr = match w, tr with
| [], Node (b, _) -> b
| h::t, Node (_, l) -> try exists t (List.assoc h l) with Not_found -> false
let rec add w tr = match w, tr with
| [], Node (_, l) -> Node (true, l)
| h :: t, Node (b, l) -> try add t (List.assoc h l)
with Not_found -> Node (false, (h, add t tr) :: l)
The problem is when List.assoc h l finds something , then I don't keep track of my structure, no Node is built during the recursive call so I am losing data.
Example :
# let empty = Node(true, []);;
- : trie = Node (true, [])
# let w = explode "hi";;
val w : char list = ['h'; 'i']
# let ww = explode "hit";;
val ww : char list = ['h'; 'i'; 't']
# let tr = add w x;;
val tr : trie = Node (false, [('h', Node (false, [('i', Node (true, []))]))])
# add ww tr;;
- : trie = Node (false, [('t', Node (true, []))])
It seems your basic plan is to work down through the data structure with List.assoc, then add your new node when you find the right spot. This makes sense if you can modify the structure. However, your data structure is immutable. With immutable data, your basic plan must be to build a new data structure rather than to modify the old one. So you have to imagine yourself finding the right spot while keeping traack of the old structure along the way, then building up a new structure starting from the spot.
Here's some code that keeps an association list counting the number of instances of characters seen so far. Note that it returns a new association list rather than modifying the old one (which is impossible):
let rec add_char_count list char =
match list with
| [] -> [(char, 1)]
| (hchar, hcount) :: t ->
if hchar = char then (hchar, hcount + 1) :: t
else (hchar, hcount) :: add_char_count t char
The recursive call (hchar, hcount) :: add_char_count t char is the spot where the old structure is remembered. It rebuilds the old structure from the part of the list before where the new character is added.

Recursive Reverse List

I need to write an algorithm called reverseNodes that takes a RefToNode as a parameter and recuriveley reverses the list the header i came up with was
Algorithm reverse (rList)
reverves elementsin a list
Pre: rList :: a referance to a list to be reversed
Post: elements in rList are reversed
if ( rList !=NULL)
reverseNodes (rList -> head)
return
I need to find a way to write this is psuedocode and find the time complexity
Sometimes it is easier to create some un-formal algorithm gibberish, if you start
with the idea expressed clearly. Then, obfuscate and verbalize until you have something, your professor will happily accept.
So, lets start with our general idea of the algorithm:
let rec fold folder acc l =
match l with
| [] -> acc
| x::xs -> fold folder (folder acc x) xs
let prepend l e = e :: l
let revlist l = fold prepend [] l
...and start to verbalize:
let result = empty list
let l = the list we want to reverse
if l is the empty list, goto 7
let head = l.front, l = l.pop_front()
result.push_front head
goto 3
l = result
The steps 3..6 can be easily expressed as a recursive function:
void loop(list& l, list& result)
{
if( l.is_empty()) return;
auto head = l.front();
l.pop_front();
result.push_front(head);
loop(l,result);
}
As we want to create the illusion of in-place.reversal, our reverse_list function is
void reverse_list( list& l )
{
list result;
loop( l, result);
l = result;
}
Alternate solution
We can also do it in another way:
let rec revlist1 l =
match l with
| [] -> l
| x::xs -> (revlist1 xs) # [x]
This basically states, that the reversed list is the front element of the original list appended to the reverse of the rest.
Translating the algorithm to gibberish form yields:
Node* reverse_list1( Node* list )
{
if( list == NULL) return NULL; // reverse of empty list is empty list.
if( list->next == NULL ) // last element in list?
return list; // the reverse of a list with 1 element is the same.
else
{
Node* head = list;
Node* tail = list->next;
head->next = NULL;
Node* end_of_reverse_tail = tail; // the first will be the last...
Node * result = reverse_list1(tail);
end_of_reverse_tail->next = head;
return result;
}
}
Note, that this is not a tail recursive solution.

Haskell IO: remove a random element from a tree

Consider the following type to represent trees:
data Tree a = Empty
| Leaf a
| Fork (Tree a) (Tree a)
I need help definig the function removeRandom' :: Tree a -> IO (Tree a) that receives a tree with at least a leaf and returns the result of removing a random leaf from the tree (replacing it with Empty). The exercise had a suggestion: use the function randomRIO :: Random a => (a,a) -> IO a to generate the order of the element to remove
EDIT: trying method 2 of user Thomas
removeRandom' :: Tree a -> IO (Tree a)
removeRandom' t = let lengthTree = numbelems t
in do x <- randomRIO (0,lengthTree -1)
return (remove x t)
numbelems :: Tree a -> Int
numbelems Empty = 0
numbelems Leaf x = 1
numbelems Fork l r = (numbelems l) + (numbelems r)
remove :: Int -> Tree a -> Tree a
remove _ (Leaf x) = Empty
remove n (Fork l r) = let lengthLeft = numbelems l
in if (n>lengthLeft) then Fork l (remove (n-lengthLeft r)
else Fork (remove n l) r
There are 2 ways to approach this problem
Convert to a list, remove the element, and convert back to a tree.
Pros: Simple to implement, you already have toList, all you need is fromList, and you can implement your solution simply as
removeAt :: Int -> [a] -> [a]
removeAt n as = a ++ tail s where (a, s) = splitAt n
removeRandom' tree = do
element <- randomRIO (0, length tree)
return $ fromList $ removeAt element $ toList tree
Cons: This method is not "True" to the problem statement removing a random leaf from the tree (replacing it with Empty) and will likely give you a brand new tree with no Empty values in it. I have only provided this as an option in an attempt to show where your toList method ends up.
Descend into the tree, until you hit the element to be removed, then rebuild the tree on the way back up
Pros: The meat of the algorithm is "Pure" as in, does not touch IO. You only actually need IO for a moment within removeRandom'. You can likely write a solution that looks a bit like this (interesting parts left blank ;).
removeAt :: Int -> Tree a -> Tree a
removeAt n tree = walk 0 tree
where
walk i Empty = ...
walk i (Fork l r) = ...
walk i l#(Leaf _)
| i == n = ...
| otherwise = ...
removeRandom' tree = do
element <- randomRIO (0, length tree)
return $ removeAt element tree
Cons: More complicated to implement, you need to know how to traverse back "up" a tree, rebuilding in your wake, and you will need to know how to write a recursive function with an accumulator such that you can track your position in the tree.
Either way you decide to go, you will need to write a function length :: Tree a -> Int that counts the number of leaves to use as input to randomRIO (which is an action that simply produces a random value in a given range).

removing cycles from cyclic/mutable list in ocaml?

I'm not sure how to remove the cycles from a mutable list of type:
type 'a m_list = Nil | Cons of 'a * (('a m_list) ref)
E.g. if I had a list 3,2,2,1,2,1,2,1,..... I would want to get a 3,2,2,1.
What I can't figure out is the location of the initial cycling--I have a recursion that looks like this but I can't figure out how to wrap this into a recursive function; obviously here it would just checks the first few terms.
let remove list : unit =
if is_cyclic list then match list with
|Nil->()
|Cons(_,v)-> match (!v) with
|Nil->()
|Cons(_,x)->match (!x) with
|Nil->()
|Cons(_,y)->match (!y) with
|Nil->()
|Cons(_,p) -> if is_cyclic (!p) then p:=Nil else ()
I have an is_cyclic function that tells me whether an m_list has a cycle or not. I'd like to do this either destructively (updating the reference) or indestructively (creating a new list).
Thanks!
Based on Pascal Cuoq's answer to your previous question, you could try something like this:
let rec recurse list already_visited =
match list with
Nil -> ()
| Cons(h, t) ->
if List.memq !t already_visited
then t := Nil
else recurse !t (t :: already_visited)
let remove_cycles list = recurse list []
This traverses the list until it either reaches the end or visits an element twice. When the latter happens, it instead sets the last visited reference to Nil.
You may want to replace already_visited with another data structure if you have very large lists.
If you don't have enough memory to store each previously visited element, you could instead using a cycle detection algorithm to find an element in the cycle, then using that, find the end of the cycle and overwrite it's next reference.
To do this, modify is_cyclic to return a 'a mlist ref instead of a bool. Assuming that it could possibly return an element in the middle of the cycle, run through the original list and check whether each element is in the cycle. This will give you the first element in the cycle.
From there it's easy to find the end of the cycle - just loop through the cycle until you get back to the beginning.
Something like this:
let rec in_cycle x st cyc =
if cyc == x then true
else
match !cyc with Nil -> false
| Cons(_, t) when t == st -> false
| Cons(_, t) -> in_cycle x st t
let rec find_start l cyc =
if in_cycle l cyc cyc then l
else
match !l with Nil -> raise Not_found
| Cons(_, t) -> find_start t cyc
let rec find_end st cyc =
match !cyc with Nil -> raise Not_found
| Cons(_, t) ->
if t == st then cyc
else find_end st t
(* ... *)
let cyc = is_cyclic list in
let st = find_start list cyc in
let e = (find_end st cyc) in
match !e with Nil -> failwith "Error"
| Cons(v, _) -> e := Cons(v, ref Nil)