module CycleQueueFunctor = functor (S : Prioqueue.SIZE) ->
struct
type priority = int
(* tablice wpf.pdf str. 95 *)
type 'a element =
| None
| Elem of 'a t
and 'a t = {
priority: priority;
element: 'a;
}
type 'a queue = {
vector: ('a element) array;
first: int ref;
elements: int ref;
}
let empty () = {
vector = Array.make S.size None;
first = ref 0;
elements = ref 0;
}
let is_empty q = !(q.elements) = 0
exception Queue_is_full
exception Unproper_use_of_queue
let rec insert q p a =
if !(q.elements) < S.size then
let e = { priority = p; element = a} in
match q.vector.(!(q.first )) with
Elem el ->
if ( e.priority < el.priority ) then
begin
q.first := ( !(q.first) - 1) mod S.size;
if !(q.first) < 0 then
q.first := !(q.first) + S.size;
q.vector.(!(q.first)) <- Elem e;
q.elements := !(q.elements) + 1;
q
end
else
begin
let t1 = ref e
and t2 = ref e
and j = ref 0 in
for i = !(q.first) to !(q.first) + !(q.elements) do
j := i mod S.size;
match q.vector.(!j) with
Elem e -> if ( (!t1).priority < e.priority ) then
begin
t2 := e;
q.vector.(!j) <- Elem !t1;
t1 := !t2;
end
(* ok, so it should really be the last element... *)
| None -> q.vector.(!j) <- Elem !t1;
done;
q.elements := !(q.elements) + 1;
q
end
| None ->
begin
q.vector.(!(q.first)) <- Elem e;
q.elements := 1;
q
end
else raise Queue_is_full
exception Queue_is_empty
exception Queue_is_empty2
let delete_min q =
if ( !(q.elements) = 0 ) then
raise Queue_is_empty
else match q.vector.(!(q.first)) with
None -> raise Unproper_use_of_queue (* <- this really should never occur *)
| Elem e ->
begin
q.vector.(!(q.first)) <- None;
q.elements := !(q.elements) - 1;
q.first := (!(q.first) + 1) mod S.size;
( e.priority, e.element, q);
end
let find_min q =
if ( !(q.elements) = 0 ) then
raise Queue_is_empty
else match q.vector.(!(q.first)) with
None -> raise Unproper_use_of_queue (* <- this really should never occur *)
| Elem e -> ( e.priority, e.element, q)
(* divides queue into two *)
let divide q =
let rec insert_and_remove from_q to_q count =
if count > 0 then
let (p, e, from_q) = delete_min from_q in
insert_and_remove from_q (insert to_q p e) (count - 1)
else
(from_q, to_q)
in
let q1 = empty()
and q2 = empty()
in
let (q_t, q1) = insert_and_remove q q1 (!(q.elements) / 2)
in
let (_, q2) = insert_and_remove q_t q2 !(q.elements)
in
match q2.vector.(!(q2.first)) with
Elem e -> (e.priority , q1, q2)
| _ -> raise Unproper_use_of_queue (* <- this really should never occur *)
(* begin *)
(* for i = !(q.first) to !(q.elements) / 2 do *)
(* q1.vector.((i - !(q.first)) mod S.size) <- q.vector.(i mod S.size); *)
(* done; *)
(* for i = !(q.elements)/2 + 1 to !(q.elements) - 1 do *)
(* q2.vector.((i - !(q.elements)/2 + 1) mod S.size) <- q.vector.(i mod S.size); *)
(* done; *)
(* match q2.vector.(0) with *)
(* Elem e -> (e.priority, q1, q2) *)
(* | _ -> raise Unproper_use_of_queue (\* <- this really should never occur *\) *)
(* end *)
end