Clojure中的固定长度堆栈结构

时间:2012-11-12 23:41:19

标签: clojure queue

固定长度堆栈(我最初称之为队列,但我想要的是堆栈)的最佳数据结构是什么,其中项目被添加到前面,每次将项目添加到前面时,项目是从最后删除?从前面也可以访问各种长度的子向量。我正在使用矢量,现在正在考虑clojure.lang.PersistentQueue和手指树。

编辑,澄清,例如:

> (def q (queue [1 2 3 4]))
[1 2 3 4]
> (push q 9 8 7)
[7 8 9 1]
> (peek (push q 9 8 7))
7

edit2:感谢你到目前为止所有的答案,这已经变成了回归基础和阅读Clojure的乐趣的练习,例如学习subvec的subvec保留对第一个subvec的向量的引用,而类似的东西( vec(cons x(subvec ...如果反复使用会产生对所有中间子集的引用。鉴于此,如何推送基于矢量的队列的推送?:

(defn push [v i n] (if (>= (count v) n) (conj (subvec v 1 n) i) (conj v i) ) )

然后可以通过rseq访问生成的向量,我相信它对向量很快(由于它使用索引偏移?)

2 个答案:

答案 0 :(得分:6)

https://github.com/amalloy/ring-buffer

查看Amalloy的环形缓冲区

答案 1 :(得分:1)

IMO你只能使用一个清单:

(defn create-queue [len]
  (atom (repeat len nil)))

(defn push [queue new-items]
  (let [len (count @queue)
        len2 (count new-items)]
    (if (>= len2 len)
      (let [res (concat (take-last (- len2 len) new-items)
                        @queue)]
        (reset! queue (take len new-items))
        res)
      (let [res (take-last len2 @queue)]
        (reset! queue (concat new-items
                              (drop-last len2 @queue)))
        res))))

试验:

(def q (create-queue 4))

(take 4 @q)
-> (nil nil nil nil)
(push q [1 2 3])
-> (nil nil nil)
(take 4 @q)
-> (1 2 3 nil)
(push q [4 5])
-> (3 nil)
(take 4 @q)
-> (4 5 1 2)
(push q [6 7 8 9])
-> (4 5 1 2)
(take 4 @q)
-> (6 7 8 9)
(push q [10 11 12 13 15 16])
-> (15 16 6 7 8 9)
(take 4 @q)
-> (10 11 12 13)