What's the best data structure for a fixed length stack (I originally called it a queue, but what I want is a stack) where items are added to the front, and every time an item is added to the front an item is removed from the end? Various lengths of subvectors will be accessed from the front also. I was using vectors, now thinking about clojure.lang.PersistentQueue and finger trees.
edit, to clarify, something like:
> (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: thanks for all your answers so far, this has turned into an exercise in going back to basics and reading Joy of Clojure, learning for instance that subvec of subvec retains a reference to the first subvec's vector, while something like (vec (cons x (subvec... would if used repeatedly accrue references to all intermediate subvecs. In light of this, how about this implementation of push for a vector-based queue ?:
(defn push [v i n] (if (>= (count v) n) (conj (subvec v 1 n) i) (conj v i) ) )
then the resulting vector could be accessed via rseq which I believe is fast with vectors (due to its use of index-offset?)
Have a look at Amalloy's ring buffer at https://github.com/amalloy/ring-buffer
IMO you can use just a list:
(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))))
test:
(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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With