我想你正在尝试实现一个queue。这可以通过多种方式完成,但如果您希望插入和删除操作都在恒定时间内执行,O(1),则必须保留对队列前面和后面的引用。
您可以将这些引用保存在一个cons 单元格中,或者像我的示例中那样,将它们包裹在一个闭包中。
术语push
和pop
通常在处理堆栈时使用,因此我已将其更改为enqueue
和dequeue
在下面的代码中。
(定义(制作队列)
(让((前面'())
(背部 '()))
(拉姆达(味精。obj)
(cond ((eq?msg 'empty?) (null?front))
((eq?msg '入队!)
(如果(空?前面)
(开始
(设置!前 obj)
(设置!返回 obj))
(开始
(set-cdr!返回 obj)
(设置!返回 obj))))
((eq?msg '出队!)
(开始
(让 ((val (车前)))
(set!front (cdr front))
验证)))
((eq?msg 'queue->list) front)))))
make-queue
返回一个过程,该过程将队列的状态包装在变量front
和back
中。这个过程接受不同的消息,这些消息将执行队列数据结构的过程。
这个过程可以这样使用:
> (定义 q (make-queue))
> (q'空?)
#t
> (q'入队!4)
> (q'空?)
#F
> (q'入队!9)
> (q '队列->列表)
(4 9)
> (q'出队!)
4
> (q '队列->列表)
(9)
这几乎是 Scheme 中的面向对象编程!您可以将front
和back
视为队列类的私有成员,将消息视为方法。
调用约定有点落后,但很容易将队列包装在更好的 API 中:
(定义(入队!队列 x)
(队列'入队!x))
(定义(出队!队列)
(队列'出队!))
(定义(空队列?队列)
(队列'空?))
(定义(队列->列表队列)
(队列'队列->列表))
编辑:
正如Eli指出的那样,在 PLT Scheme 中,pairs 默认是不可变的,这意味着没有set-car!
and set-cdr!
。要使代码在 PLT Scheme 中运行,您必须改用 可变对。在标准方案(R4RS、R5RS 或 R6RS)中,代码应该不加修改地工作。