From d986fed725b591f42bf6abcd2940800dc8cbd65b Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Wed, 23 Jun 2010 15:48:23 -0400 Subject: [PATCH] Uses a simpler single-linked list, about half of the meat code, and much faster due to the removed overhead of dealing with the redundant pointers. --- collects/tests/unstable/queue.rkt | 2 +- collects/unstable/queue.rkt | 73 ++++++++++++------------------- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/collects/tests/unstable/queue.rkt b/collects/tests/unstable/queue.rkt index 1469289343..4219832fb6 100644 --- a/collects/tests/unstable/queue.rkt +++ b/collects/tests/unstable/queue.rkt @@ -1,4 +1,4 @@ -#lang racket +#lang racket/base (require rackunit rackunit/text-ui unstable/queue "helpers.rkt") diff --git a/collects/unstable/queue.rkt b/collects/unstable/queue.rkt index 7b29ec7e86..a7a3e6ea16 100644 --- a/collects/unstable/queue.rkt +++ b/collects/unstable/queue.rkt @@ -1,56 +1,39 @@ -#lang racket -;; ELI: why is it using the `racket' language? +#lang racket/base -;; A Queue is a circularly linked list of queue structures. -;; The head of the circle is identified by the distinguished head value. -;; The top of the queue (front of the line) is to the right of the head. -;; The bottom of the queue (back of the line) is to the left of the head. -;; ELI: need to say that this is not thread-safe. -(define-struct queue (value left right) #:mutable) -;; ELI: why is `value' mutable? +;; A Queue contains a linked list with mutable cdrs, hoding two pointers +;; to the head and the tail -- where items are pulled from the head and +;; pushed on the tail. It is not thread safe: mutating a queue from +;; different threads can break it. +(struct queue (head tail) #:mutable) +;; (Note: uses #f for `head' to mark an empty queue, but in those cases +;; the tail will be set to #f too, to avoid holding on to values that +;; should be collected.) +(struct link (value [tail #:mutable])) -;; ELI: why is this needed, if nobody can get a hold of anything other -;; than the head? -(define head (gensym 'queue-head)) +(define (make-queue) (queue #f #f)) -;; ELI: if it's a single direction queue, then why is it maintaining -;; bidirectional links? -(define (empty-queue) - (let* ([q (make-queue head #f #f)]) - (set-queue-left! q q) - (set-queue-right! q q) - q)) +(define (queue-empty? q) (not (queue-head q))) -(define (queue-head? q) - (eq? (queue-value q) head)) - -(define (head-queue? v) ; ELI: `queue-head?' and `head-queue?' --?? - (and (queue? v) (queue-head? v))) - -(define (queue-empty? q) - (and (queue-head? q) (queue-head? (queue-right q)))) - -(define (nonempty-queue? v) - (and (queue? v) ; \ ELI: ...and this is `head-queue?' - (queue-head? v) ; / - (queue? (queue-right v)) ; ELI: can this ever be false? - (not (queue-head? (queue-right v))))) +(define (nonempty-queue? v) (and (queue? v) (queue-head v) #t)) (define (enqueue! q v) - (let* ([bot (queue-left q)] - [new (make-queue v bot q)]) - (set-queue-left! q new) - (set-queue-right! bot new))) + (let ([new (link v #f)]) + (if (queue-head q) + (set-link-tail! (queue-tail q) new) + (set-queue-head! q new)) + (set-queue-tail! q new))) (define (dequeue! q) - (let* ([old (queue-right q)] - [top (queue-right old)]) - (set-queue-right! q top) - (set-queue-left! top q) - (queue-value old))) + (let ([old (queue-head q)]) + (set-queue-head! q (link-tail old)) + (link-value old))) + +;; --- contracts --- + +(require racket/contract) (define queue/c - (flat-named-contract "queue" head-queue?)) + (flat-named-contract "queue" queue?)) (define nonempty-queue/c (flat-named-contract "nonempty-queue" nonempty-queue?)) @@ -58,8 +41,8 @@ (provide/contract [queue/c flat-contract?] [nonempty-queue/c flat-contract?] - [rename head-queue? queue? (-> any/c boolean?)] - [rename empty-queue make-queue (-> queue/c)] + [queue? (-> any/c boolean?)] + [make-queue (-> queue/c)] [queue-empty? (-> queue/c boolean?)] [enqueue! (-> queue/c any/c void?)] [dequeue! (-> nonempty-queue/c any/c)])