-- CoordRectPQImpl.mesa
-- A generic package to organize items
-- in a priority queue, sorted by increasing order of
-- Val.
-- customized by E. McCreight, May 21, 1982 2:11 PM
-- written by E. McCreight, February 8, 1982 2:04 PM
-- last modified by E. McCreight, February 8, 1982 2:20 PM
DIRECTORY
CoordRectPQ;
CoordRectPQImpl: PROGRAM
IMPORTS CoordRectPQ
EXPORTS CoordRectPQ SHARES CoordRectPQ =
BEGIN OPEN CoordRectPQ;
CoordRectPQUnderflow: PUBLIC SIGNAL = CODE;
NewCoordRectPQ: PUBLIC PROCEDURE[zone: UNCOUNTED ZONE,
max: CARDINAL ← 50]
RETURNS[PQHandle] =
{RETURN[zone.NEW[PQObject ← [zone: zone, size: 0,
s: zone.NEW[PQSeq[max]]]]]};
DestroyCoordRectPQ: PUBLIC PROCEDURE[p: PQHandle]
RETURNS[PQHandle] =
BEGIN
zone: UNCOUNTED ZONE ← p.zone;
zone.FREE[@p.s];
zone.FREE[@p];
RETURN[NIL];
END; -- of DestroyCoordRectPQ
InsertCoordRectPQ: PUBLIC PROCEDURE[p: PQHandle, item: Item] =
BEGIN
i, j: CARDINAL;
pqs: PQSeqPtr ← GrowingPQ[p];
p.size ← p.size+1;
FOR j ← p.size-1, i WHILE j>0 DO
i ← (j-1)/2;
IF Val[item]>=Val[pqs.heap[i]] THEN EXIT
ELSE pqs.heap[j] ← pqs.heap[i];
ENDLOOP;
pqs.heap[j] ← item;
END;
ExtractCoordRectPQ: PUBLIC PROCEDURE[p: PQHandle]
RETURNS[item: Item] =
BEGIN
pqs: PQSeqPtr ← ShrinkingPQ[p];
result: Item ← pqs.heap[0];
IF (p.size ← p.size-1)>0 THEN
BEGIN
i, j: CARDINAL;
r: CARDINAL ← p.size-1; -- max index
item: Item ← pqs.heap[p.size];
FOR i ← 0, j DO
j ← i+i+1;
IF j>r THEN EXIT;
IF j<r AND Val[pqs.heap[j+1]]<Val[pqs.heap[j]] THEN j ← j+1;
IF Val[item]<=Val[pqs.heap[j]] THEN EXIT
ELSE pqs.heap[i] ← pqs.heap[j];
ENDLOOP;
pqs.heap[i] ← item;
END;
RETURN[result];
END;
GrowingPQ: PROCEDURE[p: PQHandle] RETURNS[PQSeqPtr] =
BEGIN
IF p.size>=p.s.max THEN
BEGIN
oldSeq: PQSeqPtr ← p.s;
newSeq: PQSeqPtr ←
p.zone.NEW[PQSeq[MAX[(15*p.size)/10, 50]]];
FOR i: CARDINAL IN [0..p.size) DO
newSeq[i] ← oldSeq[i];
ENDLOOP;
p.s ← newSeq;
p.zone.FREE[@oldSeq];
END;
RETURN[p.s];
END;
ShrinkingPQ: PROCEDURE[p: PQHandle] RETURNS[PQSeqPtr] =
BEGIN
WHILE p.size<1 DO SIGNAL CoordRectPQUnderflow ENDLOOP;
IF MAX[p.size, 50]<p.s.max/2 THEN
BEGIN
oldSeq: PQSeqPtr ← p.s;
newSeq: PQSeqPtr ←
p.zone.NEW[PQSeq[MAX[(15*p.size)/10, 50]]];
FOR i: CARDINAL IN [0..p.size) DO
newSeq[i] ← oldSeq[i];
ENDLOOP;
p.s ← newSeq;
p.zone.FREE[@oldSeq];
END;
RETURN[p.s];
END;
END. -- of CoordRectPQImpl