2010-02-08 430 views
19

我正在研究一個需要循環緩衝區的Haskell中的一個小概念項目。我已經設法使用具有O(1)旋轉的數組創建緩衝區,但是當然需要O(N)來插入/刪除。我發現了一個使用列表的實現,它看起來需要O(1)來插入和刪除,但由於它保持了左右列表,所以在旋轉時會跨越一定的邊界需要O(N)時間。在命令式語言中,我可以實現帶有O(1)插入,刪除和旋轉的雙向循環緩衝區。我認爲這不可能像Haskell這樣的純粹功能語言,但我很想知道我是否錯了。O(1)haskell中的循環緩衝區?

+1

如果「道口一定邊界」時,轉動需要O(N)時間,費用是多少,當它不跨邊境?如果它是O(1),並且只有1/N的穿越邊界概率,那麼旋轉平均需要O(1)次。 – finnw 2010-02-08 16:36:03

+0

沒錯,但是做一個順序操作,你可以保證你會在某個時候交叉它,而且時間複雜度對於每次輪換都很重要,因爲這可能最終會成爲一個軟實時應用程序。 – Edward 2010-02-08 16:46:54

+0

我從來沒有使用過循環緩衝區;簡單描述你的緩衝區在做什麼很容易?在你的應用程序中是否應該「覆蓋」元素? – jberryman 2010-02-09 17:46:19

回答

4

monad允許在Haskell中描述和執行命令式算法。您可以使用STRefs作爲雙向鏈表的可變指針。

使用ST描述的自足算法使用runST執行。不同的runST執行可能不會共享ST數據結構(STRef,STArray,..)。

如果算法不是「自包含」的,並且數據結構需要在其使用之間執行IO操作時維護,則可以使用stToIOIO monad中訪問它。

關於這是純粹的功能與否 - 我猜這不是?

10

如果你能處理攤銷 O(1)操作,你很可能要麼Data.Sequence從容器包裝,或Data.Dequeue從出隊包。前者使用finger trees,而後者使用來自Okasaki的Purely Functional Data Structures(先前版本在線here)的「Banker's Dequeue」。

2

這聽起來像你可能需要一些比這更復雜的東西(因爲你提到了雙鏈表),但也許這會有所幫助。這個功能就像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' 
+1

查看關於原始問題的評論以獲取更具體的功能。 – Edward 2010-02-10 12:57:26

+0

更新了我的答案,我認爲在純粹的功能解決方案中爲您提供了所需的東西 – jberryman 2010-02-10 17:14:35

+3

順便說一下,攤銷O(1)是完全合理的 - 這隻意味着可能會發生昂貴的操作,但頻率與成反比他們的成本。例如,一個操作在大多數情況下可能是O(1),偶爾也可能是O(N),但只要後者不比每N次操作中的一次更普遍,分攤的複雜度仍然是O(1)。這對於大多數目的來說都很棒,但對於這裏的問題的評論來說,軟實時並不那麼重要...... – 2010-02-10 18:55:00