Reputation: 327
I have been given the following implementation of a doubly linked list:
type 'a elem = {v : 'a; mutable next : 'a lista; mutable prev : 'a lista}
and 'a lista = 'a elem option;;
Using this implementation I'm trying to make some example lists. A one element list is easy to make:
let bla_1 = Some {v = 1; next = None; prev = None};;
And I guess an empty list would be two None nodes. But I don't know how to make lists with more elements.
Upvotes: 1
Views: 462
Reputation: 38809
If you want to build a list with two elements x
and y
, you have to ensure you have two values of type 'a elem
pointing to each other (not counting the intermediate option type 'a lista
). Eventually, you need to have a circular structure where:
lx
is bound to { v = x; next = Some ly; prev = None }
,ly
is bound to { v = y; next = None; prev = Some lx}
You can have mutually recursive values in OCaml (thanks octhacron):
let rec x = { v = 0; next = Some y; prev = None}
and y = { v = 1; next = None; prev = Some x}
But this gets hard to use to build more complex lists. And that's why you have mutable fields: you can build nodes and then connect them by changing their next
and prev
fields. For example, you first define lx
with the next
field set to None
, and only after you know what is ly
, you can replace the value pointed by lx.next
by Some ly
.
Here below is a function that converts a regular list into a doubly-linked list; when calling itself recursively, it builds nodes; when returning from a recursive call, it modifies the next
node so that it points back through its prev
field to the current one:
let rec to_dbl_list = function
[] -> None
| x::xs ->
let node = { v = x; prev = None ; next = (to_dbl_list xs)} in
let current = Some node in
(match node.next with
None -> ()
| Some next -> (next.prev <- current)) ;
current ;;
And so:
# to_dbl_list [1; 2; 3];;
- : int lista =
Some
{v = 1;
next =
Some
{v = 2; next = Some {v = 3; next = None; prev = <cycle>}; prev = <cycle>};
prev = None}
Upvotes: 4