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.
This commit is contained in:
parent
8a5bceece1
commit
d986fed725
|
@ -1,4 +1,4 @@
|
||||||
#lang racket
|
#lang racket/base
|
||||||
|
|
||||||
(require rackunit rackunit/text-ui unstable/queue "helpers.rkt")
|
(require rackunit rackunit/text-ui unstable/queue "helpers.rkt")
|
||||||
|
|
||||||
|
|
|
@ -1,56 +1,39 @@
|
||||||
#lang racket
|
#lang racket/base
|
||||||
;; ELI: why is it using the `racket' language?
|
|
||||||
|
|
||||||
;; A Queue is a circularly linked list of queue structures.
|
;; A Queue contains a linked list with mutable cdrs, hoding two pointers
|
||||||
;; The head of the circle is identified by the distinguished head value.
|
;; to the head and the tail -- where items are pulled from the head and
|
||||||
;; The top of the queue (front of the line) is to the right of the head.
|
;; pushed on the tail. It is not thread safe: mutating a queue from
|
||||||
;; The bottom of the queue (back of the line) is to the left of the head.
|
;; different threads can break it.
|
||||||
;; ELI: need to say that this is not thread-safe.
|
(struct queue (head tail) #:mutable)
|
||||||
(define-struct queue (value left right) #:mutable)
|
;; (Note: uses #f for `head' to mark an empty queue, but in those cases
|
||||||
;; ELI: why is `value' mutable?
|
;; 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
|
(define (make-queue) (queue #f #f))
|
||||||
;; than the head?
|
|
||||||
(define head (gensym 'queue-head))
|
|
||||||
|
|
||||||
;; ELI: if it's a single direction queue, then why is it maintaining
|
(define (queue-empty? q) (not (queue-head q)))
|
||||||
;; 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-head? q)
|
(define (nonempty-queue? v) (and (queue? v) (queue-head v) #t))
|
||||||
(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 (enqueue! q v)
|
(define (enqueue! q v)
|
||||||
(let* ([bot (queue-left q)]
|
(let ([new (link v #f)])
|
||||||
[new (make-queue v bot q)])
|
(if (queue-head q)
|
||||||
(set-queue-left! q new)
|
(set-link-tail! (queue-tail q) new)
|
||||||
(set-queue-right! bot new)))
|
(set-queue-head! q new))
|
||||||
|
(set-queue-tail! q new)))
|
||||||
|
|
||||||
(define (dequeue! q)
|
(define (dequeue! q)
|
||||||
(let* ([old (queue-right q)]
|
(let ([old (queue-head q)])
|
||||||
[top (queue-right old)])
|
(set-queue-head! q (link-tail old))
|
||||||
(set-queue-right! q top)
|
(link-value old)))
|
||||||
(set-queue-left! top q)
|
|
||||||
(queue-value old)))
|
;; --- contracts ---
|
||||||
|
|
||||||
|
(require racket/contract)
|
||||||
|
|
||||||
(define queue/c
|
(define queue/c
|
||||||
(flat-named-contract "queue" head-queue?))
|
(flat-named-contract "queue" queue?))
|
||||||
|
|
||||||
(define nonempty-queue/c
|
(define nonempty-queue/c
|
||||||
(flat-named-contract "nonempty-queue" nonempty-queue?))
|
(flat-named-contract "nonempty-queue" nonempty-queue?))
|
||||||
|
@ -58,8 +41,8 @@
|
||||||
(provide/contract
|
(provide/contract
|
||||||
[queue/c flat-contract?]
|
[queue/c flat-contract?]
|
||||||
[nonempty-queue/c flat-contract?]
|
[nonempty-queue/c flat-contract?]
|
||||||
[rename head-queue? queue? (-> any/c boolean?)]
|
[queue? (-> any/c boolean?)]
|
||||||
[rename empty-queue make-queue (-> queue/c)]
|
[make-queue (-> queue/c)]
|
||||||
[queue-empty? (-> queue/c boolean?)]
|
[queue-empty? (-> queue/c boolean?)]
|
||||||
[enqueue! (-> queue/c any/c void?)]
|
[enqueue! (-> queue/c any/c void?)]
|
||||||
[dequeue! (-> nonempty-queue/c any/c)])
|
[dequeue! (-> nonempty-queue/c any/c)])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user