2011-10-27 6 views
3

私は、コードの一部にベクトルを使うのが効率的なアプリケーションを持っています。しかし、計算中にいくつかの要素を追跡する必要があります。私はData.VectorsからO(n)償却連結を得ることができると聞いていますが(通常の配列成長トリックで)、私は正しいことをしていないと思います。だから我々は次のセットアップを持って言うことができます:Data.Vectorから償却されたO(n)連結を確実にする方法はありますか?

import Data.Vector((++),Vector) 
import Prelude hiding ((++)) 
import Control.Monad.State.Strict 

data App = S (Vector Int) 

add :: Vector Int -> State App() 
add v1 = modify (\S v2 -> S (v2 ++ v1)) 

い、この場合の償却O(n)の時間でadd動作しますか?そうでない場合は、どうすればaddを行うことができますか((forall s. MVector s Int)を状態に保存する必要がありますか?)。 addを実装する効率的な方法はありますか?

+0

@hvr上で最も二回コピーされることを保証する、少なくとも2倍の成長、それが空きスペースに収まらない場合

  • を成長させずに凍結:いいえそれはありません私が望むもの私は私の質問で正しくそれをやっていないと確信しています。しかし、私はData.Vectorライブラリをよく知っていませんし、ドキュメント '(++)'は* O(m + n)*最悪の場合のみ* O(n)*償却されたランタイム。 – HaskellElephant

  • +0

    StackOverflowの人々が質問のある質問に答えると嫌いですが、私はそれをやろうとしています:P - なぜあなたは「間違っている」と思いますか?私はあなたが '' State''をこの質問に無関係な何らかの理由で使用していると仮定していますので、 '' State'関連のものを取り除くと、あなたは何も狂っていないことが明らかです:<! - language:lang- > add :: Vector Int - > Vector Int - > Vector Int add v1 v2 = v1 ++ v2 - ドキュメントが* O(n + m)*時間で実行されていることに気づいた。何があなたをより速く走らせるべきだと信じさせたのですか? – mergeconflict

    +0

    間違っているかもしれませんが、私は追加が 'O(n^2)*最悪の場合に終わるかもしれないことを認識していると言いたいと思っています。また、* O(n + m)*最悪の場合、何かが実行される可能性がありますが、* O(n)*で実行される可能性があることに注意してください。* MVectorが成長することができる、 /hackage.haskell.org/packages/archive/vector/0.9/doc/html/Data-Vector-Storable-Mutable.html#g:8)、どこかで聞いたと思います。私が州を含めた理由は明らかではないことが分かっています。それは私が自分のアプリケーションでやっていることであり、私は他のタイプを保存するかもしれないので全く無関係ではありません。 – HaskellElephant

    答えて

    2

    私はベクターライブラリーもよく知らないので、一般的な原則に固執する必要があります。それをベンチマークして、アプリケーションで期待するものと似た一連の追加を実行し、どのようなパフォーマンスが得られるかを確認します。それが「十分に良い」ならば、シンプルなコードに固執してください。そうでない場合は、(forall s. MVector s Int)を状態に保存する前に(タプルはすべての型を保持できないため、ラップする必要があります)、可変ビヘイビアに変換して追加ビヘイビアを改善し、フリーズする前に連結して、もう一度不変ベクトルを得ることができます。

    add v1 = do 
        S v2 <- get 
        let v3 = runST $ do 
           m1 <- unsafeThaw v2 
           m2 <- unsafeGrow m1 (length v1) 
           -- copy contents of v1 behind contents of v2 
           unsafeFreeze m2 
        put (S v3) 
    

    ここに厳密性を挿入する必要があります。ただし、unsafeGrowがコピーする必要がある場合、償却されたO(n)の動作は保証されません。

    新しいベクトルが最後に空きスペースに収まる場合は、

  • すぎた状態で使用スロットの数を格納

    1. によって償却O(n)の動作を得ることができ、解凍、コピー、各要素は平均
  • +0

    質問に追加された順番が間違っていたので変更しました。最初のケースはあなたの質問で私が何をしたかです... – HaskellElephant

    +0

    修正された質問に合わせて更新されました。 –

    +0

    私は間違っているかもしれませんが、私は想像していないO(n)を得ると思います.2倍の成長係数は必要ありません。私はそれがちょうど1より大きくなければならないと思います。小さなリストで1要素分)。 –

    関連する問題