我想你試圖實施queue。這可以通過多種方式完成,但是如果您希望插入操作和刪除操作都在恆定時間內執行,則O(1)必須保持對隊列的正面和背面的引用。
您可以將這些引用保留在cons cell中,或者像我的示例中所示,封裝在閉包中。
的術語push
和pop
與堆打交道時通常使用的,所以在下面的代碼中,我已經改變了這些對enqueue
和dequeue
。
(define (make-queue)
(let ((front '())
(back '()))
(lambda (msg . obj)
(cond ((eq? msg 'empty?) (null? front))
((eq? msg 'enqueue!)
(if (null? front)
(begin
(set! front obj)
(set! back obj))
(begin
(set-cdr! back obj)
(set! back obj))))
((eq? msg 'dequeue!)
(begin
(let ((val (car front)))
(set! front (cdr front))
val)))
((eq? msg 'queue->list) front)))))
make-queue
返回它包裝在變量front
和back
隊列的狀態的過程。該過程接受將執行隊列數據結構的過程的不同消息。
這個程序可以像這樣使用:
> (define q (make-queue))
> (q 'empty?)
#t
> (q 'enqueue! 4)
> (q 'empty?)
#f
> (q 'enqueue! 9)
> (q 'queue->list)
(4 9)
> (q 'dequeue!)
4
> (q 'queue->list)
(9)
這幾乎對象計劃面向對象編程!您可以將front
和back
視爲隊列類的私有成員,並將消息視爲方法。
調用約定是有點落後,但它是容易將保鮮膜隊列一個更好的API中:
(define (enqueue! queue x)
(queue 'enqueue! x))
(define (dequeue! queue)
(queue 'dequeue!))
(define (empty-queue? queue)
(queue 'empty?))
(define (queue->list queue)
(queue 'queue->list))
編輯:
由於Eli指出,對在默認情況下是immutable PLT計劃,這意味着沒有set-car!
和set-cdr!
。要使代碼在PLT方案中工作,您必須改用mutable pairs。在標準方案(R4RS,R5RS或R6RS)中,代碼應該不加修改地工作。
我很抱歉,但我想等待更好的代碼。 – unj2 2009-06-25 01:10:04
雖然我同意這不是很好的代碼,但它的用途是爲什麼你的工作不正常。也就是說,應該使用更復雜的數據結構來處理隊列中的隊列。祝你在實現這個答案時最好。 – Sev 2009-06-25 01:12:26