在Clojure中獲取簡單,高效的不可變隊列數據類型的最佳方式是什麼?Clojure中的不可變隊列
它只需要兩個操作,入隊和出隊與通常的語義。
我認爲是當然的名單和載體,但據我所知,他們的表現相對較差(即O(N)或更糟)進行修改,在年底分別開始 - 所以不理想的隊列!
理想我想和O(log n)的兩個入隊和出隊操作的適當的持久數據結構。
在Clojure中獲取簡單,高效的不可變隊列數據類型的最佳方式是什麼?Clojure中的不可變隊列
它只需要兩個操作,入隊和出隊與通常的語義。
我認爲是當然的名單和載體,但據我所知,他們的表現相對較差(即O(N)或更糟)進行修改,在年底分別開始 - 所以不理想的隊列!
理想我想和O(log n)的兩個入隊和出隊操作的適當的持久數據結構。
問題已解決 - 爲其他人提供的解決方案可能會對您有所幫助。
我發現Clojure的有clojure.lang.PersistentQueue的類,它需要什麼。
您可以創建這樣一個實例:據我所看到的,你現在需要互操作使用Java創建實例,但作爲米哈爾有益指出,你可以使用偷看,流行
(def x (atom clojure.lang.PersistentQueue/EMPTY))
然後連接。
我用下面的函數queue
創建PersistentQueue。或者,如果要打印和讀取隊列,您可能需要使用打印方法和數據讀取器。
通常的Clojure函數已經實現了PersistentQueue。
(defn queue
([] clojure.lang.PersistentQueue/EMPTY)
([coll] (reduce conj clojure.lang.PersistentQueue/EMPTY coll)))
(defmethod print-method clojure.lang.PersistentQueue
[q ^java.io.Writer w]
(.write w "#queue ")
(print-method (sequence q) w))
(comment
(let [*data-readers* {'queue #'queue}]
(read-string (pr-str (queue [1 2 3])))))
Clojure中能真正從字面隊列中受益。這將比依靠Java interop更清潔(並且更便於攜帶)。
但是,使用普通家庭項目(如列表)來推出自己的可移植持久隊列並不難。
將隊列看作兩個列表,一個提供隊列的頭部分,另一個提供尾部。 enqueue
添加到第一個列表中,dequeue
從後者彈出。大多數ISeq
函數都可以實現。
大概是唯一棘手的部分是當尾巴是空的,你想dequeue
會發生什麼。在這種情況下,頭部列表爲reverse
d,併成爲新尾部,空列表成爲新頭部列表。我相信,即使有reverse
的開銷,即enqueue
和dequeue
保持O(1)
,雖然k
將是當然比一個香草矢量更高。
快樂queue
ing!
爲了避免人們寫作如何使用缺點列表來實現推送/彈出棧(就像我差不多),不要忘記問題是關於* queues *。 :-) – 2010-06-28 22:05:08
剛剛注意到在最新的1.2快照Clojure Java源代碼中有一個名爲PersistentQueue的類....可能是我自己的問題的答案 – mikera 2010-06-28 22:09:07
它一直在那裏,因爲永遠(剛剛檢查過1.1,但我認爲它比較老比起那個來說)。請注意,默認情況下不提供工廠函數和讀取器語法;使用'clojure.lang.PersistentQueue/EMPTY'來獲得一個空的實例。然後'conj','pop'和'peek'就像他們應該用一個隊列一樣工作。見例如我對這個問題的回答:http://stackoverflow.com/questions/2760017用'c.l.PQ'和Java'LinkedBlockingQueue'編寫的代碼。 – 2010-06-28 22:31:11