From b68110802b2883ded61665655769b6bea178c977 Mon Sep 17 00:00:00 2001 From: oldk1331 Date: Fri, 24 Jun 2016 12:44:55 +0800 Subject: [PATCH] more efficient Rep for Queue and Dequeue --- src/algebra/Makefile.in | 2 +- src/algebra/aggcat.spad | 7 +- src/algebra/bags.spad | 165 +++++++++++++++++++++++++++++----------- 3 files changed, 128 insertions(+), 46 deletions(-) diff --git a/src/algebra/Makefile.in b/src/algebra/Makefile.in index 1804ee818..d9c192220 100644 --- a/src/algebra/Makefile.in +++ b/src/algebra/Makefile.in @@ -358,7 +358,7 @@ CATDOMS= A1AGG ABELGRP ABELMON ABELSG ACF ACFS AGG ALGEBRA AMR ARR2CAT \ LNAGG LODOCAT LSAGG LZSTAGG MAGMA MAGMAWU MATCAT MODULE \ MONOGEN MONOID MTSCAT NAALG NARING NARNG NASRNG \ OC OM ORDRING ORDSET OREPCAT \ - PDRING PFECAT POLYCAT PORDER POSET PSCAT PSETCAT QFCAT QUATCAT RADCAT \ + PDRING PFECAT POLYCAT PORDER POSET PSCAT PSETCAT QFCAT QUAGG QUATCAT RADCAT \ RCAGG RCFIELD RETFROM RETRACT RING RMATCAT RNG \ RNS RPOLCAT RRCC RSETCAT \ SETAGG SETCAT SGROUP SMATCAT SPTCAT SRAGG STAGG TBAGG TENSPC TRANFUN \ diff --git a/src/algebra/aggcat.spad b/src/algebra/aggcat.spad index ede39cc88..37b9745e1 100644 --- a/src/algebra/aggcat.spad +++ b/src/algebra/aggcat.spad @@ -320,7 +320,7 @@ QueueAggregate(S : Type) : Category == Join(BagAggregate S, finiteAggregate) wit rotate! : % -> % ++ rotate! q rotates queue q so that the element at the front of ++ the queue goes to the back of the queue. - ++ Note: rotate! q is equivalent to enqueue!(dequeue!(q)). + ++ Note: rotate! q is equivalent to (enqueue!(dequeue! q, q); q). front : % -> S ++ front(q) returns the element at the front of the queue. ++ The queue q is unchanged by this operation. @@ -329,6 +329,11 @@ QueueAggregate(S : Type) : Category == Join(BagAggregate S, finiteAggregate) wit ++ back(q) returns the element at the back of the queue. ++ The queue q is unchanged by this operation. ++ Error: if q is empty. + add + rotate! q == + empty? q => q + enqueue!(dequeue! q, q) + q )abbrev category DQAGG DequeueAggregate ++ Author: Michael Monagan; revised by Manuel Bronstein and Richard Jenks diff --git a/src/algebra/bags.spad b/src/algebra/bags.spad index 4b8201874..6f022e5f4 100644 --- a/src/algebra/bags.spad +++ b/src/algebra/bags.spad @@ -109,32 +109,58 @@ ArrayStack(S : SetCategory) : StackAggregate(S) with ++ References: ++ Description: -++ Linked List implementation of a Queue ---% Dequeue and Heap data types - Queue(S : SetCategory) : QueueAggregate S with queue : List S -> % ++ queue([x, y, ..., z]) creates a queue with first (top) ++ element x, second element y, ..., and last (bottom) element z. - == Stack S add - Rep := Reference List S - lastTail==> LAST$Lisp + == add + Rep := Record(front: List S, rear: List S) + + queue q == construct q + construct q == [q, []] + empty() == [[], []] + empty? q == empty? q.front and empty? q.rear + copy q == [copy q.front, copy q.rear] + map(f, q) == + [map(f, q.front), reverse! map!(f, reverse q.rear)] + map!(f, q) == + q.front := map!(f, q.front) + q.rear := reverse! map!(f, reverse! q.rear) + q + # q == # q.front + # q.rear + parts q == append(q.front, reverse q.rear) + hashUpdate!(st, q) == hashUpdate!(st, parts q) + + -- QueueAggregate's exclusive operations enqueue!(e, q) == - if null deref q then setref(q, list e) - else lastTail.(deref q).rest := list e + q.rear := cons(e, q.rear) e - insert!(e, q) == (enqueue!(e, q);q) + dequeue! q == - empty? q => error "empty queue" - e := first deref q - setref(q, rest deref q) + if empty? q.front then + empty? q.rear => error "empty queue" + q.front := reverse! q.rear + q.rear := [] + e := first q.front + q.front := rest q.front e + + front q == + empty? q.front => + empty? q.rear => error "empty queue" + last q.rear + first q.front + + back q == + empty? q.rear => + empty? q.front => error "empty queue" + last q.front + first q.rear + + -- BagAggregate's exclusive operations + insert!(e, q) == (enqueue!(e, q); q) extract! q == dequeue! q - rotate! q == if empty? q then q else (enqueue!(dequeue! q, q); q) - front q == if empty? q then error "empty queue" else first deref q inspect q == front q - back q == if empty? q then error "empty queue" else last deref q - queue q == construct(q) )abbrev domain DEQUEUE Dequeue ++ Author: Michael Monagan and Stephen Watt @@ -148,45 +174,96 @@ Queue(S : SetCategory) : QueueAggregate S with ++ References: ++ Description: -++ Linked list implementation of a Dequeue ---% Dequeue and Heap data types - Dequeue(S : SetCategory) : DequeueAggregate S with dequeue : List S -> % ++ dequeue([x, y, ..., z]) creates a dequeue with first (top or front) ++ element x, second element y, ..., and last (bottom or back) element z. == Queue S add - Rep := Reference List S - bottom d == - if empty? d then error "empty dequeue" else last deref d - dequeue d == construct(d) - extractBottom! d == - if empty? d then error "empty dequeue" - p := deref d - n := maxIndex p - n = 1 => - r := first p - setref(d, []) - r - q := rest(p, (n-2)::NonNegativeInteger) - r := first rest q - q.rest := [] - r + Rep := Record(front: List S, rear: List S) + + -- empty, empty? copy, map, map!, #, parts, hashUpdate! are provided by Queue S + dequeue d == [copy d, []] + construct d == dequeue d + + -- if front or rear is empty, try to balance the dequeue + -- balance! try to ensure front non-empty, unless the dequeue is empty + balance!(d : %) : % == + if empty? d.front then + empty? d.rear => return d + n := # d.rear + n = 1 => + d.front := d.rear + d.rear := [] + return d + d.front := reverse! split!(d.rear, n quo 2) + return d + if empty? d.rear then + n := # d.front + n = 1 => return d + d.rear := reverse! split!(d.front, n quo 2) + d + + -- DequeueAggregate's exclusive operations extractTop! d == - e := top d - setref(d, rest deref d) + if empty? d.front then + empty? d.rear => error "empty dequeue" + balance! d + e := first d.front + d.front := rest d.front + e + + extractBottom! d == + if empty? d.rear then + empty? d.front => error "empty dequeue" + if null rest d.front then + -- have 1 element in d + e := first d.front + d.front := [] + return e + balance! d + e := first d.rear + d.rear := rest d.rear + e + + insertTop!(e, d) == + d.front := cons(e, d.front) e - insertTop!(e, d) == (setref(d, cons(e, deref d)); e) - lastTail==> LAST$Lisp + insertBottom!(e, d) == - if empty? d then setref(d, list e) - else lastTail.(deref d).rest := list e + d.rear := cons(e, d.rear) e - top d == if empty? d then error "empty dequeue" else first deref d - reverse! d == (setref(d, reverse deref d); d) - pop!(d) == extractTop!(d) + + reverse! d == + empty? d => d + (d.front, d.rear) := (d.rear, d.front) + d + + bottom d == + empty? d.rear => + empty? d.front => error "empty dequeue" + last d.front + first d.rear + + -- QueueAggregate's exclusive operations + front d == + empty? d.front => + empty? d.rear => error "empty dequeue" + last d.rear + first d.front + enqueue!(e, d) == insertBottom!(e, d) + dequeue! d == extractTop! d + back d == bottom d + + -- StackAggregate's exclusive operations + top d == front d + pop! d == extractTop! d push!(e, d) == insertTop!(e, d) + -- BagAggregate's exclusive operations + insert!(e, d) == (insertBottom!(e, d); d) + extract! d == extractTop! d + inspect d == front d + )abbrev domain HEAP Heap ++ Author: Michael Monagan and Stephen Watt ++ Date Created: June 86 and July 87