我正在研究一個需要循環緩衝區的Haskell中的一個小概念項目。我已經設法使用具有O(1)旋轉的數組創建緩衝區,但是當然需要O(N)來插入/刪除。我發現了一個使用列表的實現,它看起來需要O(1)來插入和刪除,但由於它保持了左右列表,所以在旋轉時會跨越一定的邊界需要O(N)時間。在命令式語言中,我可以實現帶有O(1)插入,刪除和旋轉的雙向循環緩衝區。我認爲這不可能像Haskell這樣的純粹功能語言,但我很想知道我是否錯了。O(1)haskell中的循環緩衝區?
回答
monad允許在Haskell中描述和執行命令式算法。您可以使用STRef
s作爲雙向鏈表的可變指針。
使用ST
描述的自足算法使用runST
執行。不同的runST
執行可能不會共享ST
數據結構(STRef
,STArray
,..)。
如果算法不是「自包含」的,並且數據結構需要在其使用之間執行IO操作時維護,則可以使用stToIO
在IO
monad中訪問它。
關於這是純粹的功能與否 - 我猜這不是?
如果你能處理攤銷 O(1)操作,你很可能要麼Data.Sequence
從容器包裝,或Data.Dequeue
從出隊包。前者使用finger trees,而後者使用來自Okasaki的Purely Functional Data Structures(先前版本在線here)的「Banker's Dequeue」。
這聽起來像你可能需要一些比這更復雜的東西(因爲你提到了雙鏈表),但也許這會有所幫助。這個功能就像map
在一個可變循環列表:
mapOnCycling f = concat . tail . iterate (map f)
使用,如:
*Main> (+1) `mapOnCycling` [3,2,1]
[4,3,2,5,4,3,6,5,4,7,6,5,8,7,6,9,8,7,10,9...]
這裏還有一個就像mapAccumL:
mapAccumLOnCycling f acc xs =
let (acc', xs') = mapAccumL f acc xs
in xs' ++ mapAccumLOnCycling f acc' xs'
無論如何,如果你願意細說甚至更重要的是你的數據結構需要能夠「做什麼」,我真的很有興趣聽到它。
編輯:如camccann提到的,你可以使用Data.Sequence
用於此目的,根據文檔應該給你O1的時間複雜度(出現這樣的事,作爲O1攤銷時間?)觀看或添加元素同時向序列的左側和右側,以及沿途修改末端。這是否會有你需要的表現,我不確定。
您可以將「當前位置」視爲序列的左端。在這裏,我們沿着一個序列來回穿梭,產生無限的價值清單。很抱歉,如果它不能編譯,我沒有GHC的時刻:
shuttle (viewl-> a <: as) = a : shuttle $ rotate (a+1 <| as)
where rotate | even a = rotateForward
| otherwise = rotateBack
rotateBack (viewr-> as' :> a') = a' <| as'
rotateForward (viewl-> a' <: as') = as' |> a'
查看關於原始問題的評論以獲取更具體的功能。 – Edward 2010-02-10 12:57:26
更新了我的答案,我認爲在純粹的功能解決方案中爲您提供了所需的東西 – jberryman 2010-02-10 17:14:35
順便說一下,攤銷O(1)是完全合理的 - 這隻意味着可能會發生昂貴的操作,但頻率與成反比他們的成本。例如,一個操作在大多數情況下可能是O(1),偶爾也可能是O(N),但只要後者不比每N次操作中的一次更普遍,分攤的複雜度仍然是O(1)。這對於大多數目的來說都很棒,但對於這裏的問題的評論來說,軟實時並不那麼重要...... – 2010-02-10 18:55:00
- 1. haskell中的固定長度循環緩衝區
- 2. 高效循環緩衝區?
- 3. 循環緩衝區優化
- 4. 逆循環緩衝區
- 5. 縮小循環緩衝區
- 6. 循環緩衝區「requestBufferSize:couchbase
- 7. ActionScript3中的循環視頻緩衝區
- 8. Java中的循環緩衝區?
- 9. VB.NET中的循環緩衝區
- 10. Simulink中的循環緩衝區
- 11. 爲什麼我的環形緩衝區/循環緩衝區在java打破?
- 12. 使用SQL的循環緩衝區
- 13. 矢量的循環緩衝區
- 14. 循環緩衝區的線程安全
- 15. 線程安全循環緩衝區?
- 16. Qt和Boost循環緩衝區
- 17. 循環字符數組緩衝區 - c
- 18. 瞭解Linux內核循環緩衝區
- 19. 斯卡拉集合循環緩衝區
- 20. C++簡單循環緩衝區隊列
- 21. 發佈WEB音頻緩衝區循環
- 22. 嘗試在循環緩衝區 - Javascript
- 23. Qt是否有循環緩衝區?
- 24. 循環通過緩衝區在Emacs
- 25. 如何在C中實現循環列表(環形緩衝區)?
- 26. 雙緩衝區設計I/O同步
- 27. Java:I/O,read()不會填充緩衝區?
- 28. Linux內核中磁盤文件的I/O緩衝區緩存
- 29. 用於循環/環形緩衝區的npm託管庫
- 30. 在c#中的串行端口的循環緩衝區#
如果「道口一定邊界」時,轉動需要O(N)時間,費用是多少,當它不跨邊境?如果它是O(1),並且只有1/N的穿越邊界概率,那麼旋轉平均需要O(1)次。 – finnw 2010-02-08 16:36:03
沒錯,但是做一個順序操作,你可以保證你會在某個時候交叉它,而且時間複雜度對於每次輪換都很重要,因爲這可能最終會成爲一個軟實時應用程序。 – Edward 2010-02-08 16:46:54
我從來沒有使用過循環緩衝區;簡單描述你的緩衝區在做什麼很容易?在你的應用程序中是否應該「覆蓋」元素? – jberryman 2010-02-09 17:46:19