;; open Assert module type QUEUE = sig (* type of the data structure *) type 'a queue (* Make a new, empty queue *) val create : unit -> 'a queue (* Determine if the queue is empty *) val is_empty : 'a queue -> bool (* Add a value to the tail of the queue *) val enq : 'a -> 'a queue -> unit (* Remove the head value and return it (if any) *) val deq : 'a queue -> 'a (* Return a list of elements in the queue *) val to_list : 'a queue -> 'a list end (* An inefficient implementation of queues that uses linked lists. *) module ListQ : QUEUE = struct type 'a queue = 'a list ref let create () : 'a queue = ref [] let is_empty (q:'a queue) : bool = !q = [] let enq (x:'a) (q:'a queue) : unit = q := (!q @ [x]) let deq (q:'a queue) : 'a = begin match !q with | [] -> failwith "deq called on empty queue" | x::tl -> q := tl; x end let to_list (q:'a queue) : 'a list = !q end (* Some test cases for the queue *) ;; open ListQ let test () : bool = let q : int queue = create () in enq 1 q; enq 2 q; 1 = deq q ;; run_test "queue test 1" test let test () : bool = let q : int queue = create () in enq 1 q; enq 2 q; let _ = deq q in 2 = deq q ;; run_test "queue test 2" test (*************************) (* Mutable linked queues *) (*************************) module Q : QUEUE = struct (* Here are the datatypes for mutable queues *) type 'a queuenode = { v: 'a; mutable next : 'a queuenode option} type 'a queue = { mutable head : 'a queuenode option; mutable tail : 'a queuenode option } (* A valid queue structure will satisfy these INVARIANTS: - q.head and q.tail are either both None, or - q.head and q.tail both point to Some nodes, and - q.tail is reachable by following 'next' pointers from q.head, and - q.tail's next pointer is None *) (* create an empty queue *) let create () : 'a queue = { head = None; tail = None } (* determine whether a queue is empty *) let is_empty (q:'a queue) : bool = q.head = None (* add an element to the tail of a queue *) let enq (x: 'a) (q: 'a queue) : unit = let newnode = {v=x; next=None} in begin match q.tail with | None -> (* Note that the invariant tells us that q.head is also None *) q.head <- Some newnode; q.tail <- Some newnode | Some n -> n.next <- Some newnode; q.tail <- Some newnode end (* remove an element from the head of the queue *) let deq (q: 'a queue) : 'a = begin match q.head with | None -> failwith "deq called on empty queue" | Some n -> q.head <- n.next; if n.next = None then q.tail <- None; n.v end (* In this version, the size of the stack is proportional to the length of the queue *) let to_list_recursive (q:'a queue) : 'a list = let rec loop (no: 'a queuenode option) : 'a list = begin match no with | None -> [] | Some n -> n.v :: (loop n.next) end in loop q.head (* Retrieve the list of values stored in the queue, ordered from head to tail. *) let to_list (q: 'a queue) : 'a list = let rec loop (no: 'a queuenode option) (l:'a list) : 'a list = begin match no with | None -> List.rev l | Some n -> loop n.next (n.v::l) end in loop q.head [] end