2012-11-12 9 views
7

Jaka jest najlepsza struktura danych dla stosu o ustalonej długości (początkowo nazywam to kolejką, ale to, czego chcę, to stos), gdzie elementy są dodawane z przodu i za każdym razem, gdy element jest dodawany z przodu przedmiot jest usuwany z końca? Różne długości podvektorów będą dostępne również z przodu. Używałem wektorów, teraz myślę o clojure.lang.PersistentQueue i palcach.Stała struktura stosu w Clojure

edycja, w celu wyjaśnienia, coś takiego:

> (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: Dzięki za wszystkie odpowiedzi tak daleko, to stał się ćwiczeniem wracając do podstaw i czytanie Joy of Clojure, uczących się na przykład, że subvec z subvec zachowuje odwołanie do wektora pierwszego subvec, podczas gdy coś takiego jak (vec (cons x (subvec ..., jeśli byłby używany wielokrotnie powtarzały odniesienia do wszystkich pośrednich subvec .W świetle tego, jak o tej realizacji push for a vector w kolejce?:

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

następnie uzyskany wektor mogą być dostępne za pośrednictwem rseq który moim zdaniem jest szybki wektorami (z powodu jego użycia indeksu offset?)

Odpowiedz

6

Wystarczy popatrzeć na buforze pierścieniowym Amalloy pod adresem https://github.com/amalloy/ring-buffer

+4

Dangit! Kradnąc moją reputację SO, łącząc się z moją biblioteką? Oczywiście, że jestem dzieciakiem. Właściwie to jestem ciekawa, jak to znalazłeś, ponieważ nie reklamowałem go w ogóle, a wyszukiwarka google dla 'clojure ring buffer' nie ujawnia niczego strasznie łatwo. – amalloy

+0

Znalazłem go w Google w pewnym momencie i teraz jest w moich zakładkach;). Dzięki! – DanLebrero

+1

Przepraszam za wyjaśnienie, ring-buffer byłby idealny, gdyby jego elementy zostały dodane i zerknął z przodu i wyrzucony od końca. Jest to ten sam problem, który miałem z PersistentQueue: conj dodaje się do końca, ale zerkam z przodu, ale zależy mi tylko na najnowszych elementach (lifo) z najstarszymi przedmiotami usuniętymi najpierw – Hendekagon

1

IMO można używać tylko lista:

(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) 
+0

ok, ale używałem już wektorów.Nie widzę potrzeby atom tutaj – Hendekagon

+0

I brakowało ostatniego zdania twojego pytania na temat wektorów :) Nie, potrzebujemy stm tutaj.Dodatkowo, dla bezpiecznego wątku, potrzebujemy ref zamiast atomu i wykonujemy całą pracę w dosync – mobyte

+0

hmm, wolałbym trwałą strukturę – Hendekagon