償却された一定時間で配列を初期化します—このトリックは何と呼ばれますか?


13

配列アクセスのパフォーマンスと、それをクリアするときに反復処理する必要性とを引き換えにするこのデータ構造があります。エントリごとに生成カウンターを保持し、グローバル生成カウンターも保持します。「クリア」操作は、生成カウンターを増やします。各アクセスで、ローカル生成カウンターとグローバル生成カウンターを比較します。それらが異なる場合、値は「クリーン」として扱われます。

これは最近Stack Overflowでのこの回答で出てきましたが、このトリックに正式な名前があるかどうかは覚えていません。そうですか?

1つのユースケースは、ノードのごく一部のみを緩和する必要がある場合、およびこれを繰り返し行う必要がある場合のダイクストラのアルゴリズムです。


2
興味深いトリックですが、かなりオーバーヘッドがあります。だから、どの用途が価格を払うほどの一般的な操作として配列をクリアしているのだろうか?(誠実な質問!)
ヨアヒムザウアー

@JoachimSauer:編集。
krlmlr

メモリ使用量とアクセスコストの両方について、一般的なケースでは非常に高価に聞こえます。この手法の使用例は非常に具体的でなければなりません。
マーティンヨーク

3
@Joachim:レンダリングのバッファを高速でクリアするために使用されます-大まかに。64kbあたりの「クリアビット」などがあります。
-DeadMG

3
@ user946850「償却」とは、全体像でコストのかかる操作がまれにしか発生しないことを証明できることを意味します。たとえば、O(1)

回答:


2

前述のアプローチでは、各セルが、アレイを再初期化する必要がある回数を保持するのに十分な数を保持できる必要があり、これはかなりのスペースのペナルティです。スロットは、合法的に書き込まれることはありません少なくとも一つの値を保持することが可能である場合、一つは追加の費用で、他の(非定数)空間ペナルティを回避することができるO(Wlg(N))時間のペナルティを、W数で異なる配列スロットの間に書かれ消去操作でありN、配列のサイズです。たとえば、-2,147,483,647から2,147,483,647の整数を格納し(ただし、-2,147,483,648は絶対に格納しない)、空の配列項目を0として読み込む必要があるとします。配列に-2,147,483,648を入力することから始めます(その値を呼び出しますB)。アプリケーションの配列スロットを読み取るとき、値Bとしてゼロを報告します。アレイのスロットを書き込む前にI、それを保持するかどうかをチェックBし、そうであればI1より大きい、スロットにゼロを記憶されI/4(それが保持していた場合、その位置のために同様の検査を行った後BI/16など)。

配列をクリアするIには、配列のベースに応じて0または1から始めます(説明したアルゴリズムはどちらでも機能します)。次に、次の手順を繰り返します。itemがの場合、インクリメントし、4の倍数になる場合IBI4で除算します(除算の値が1の場合は終了します)。アイテムIがでない場合はBBそこに保存Iして4 倍Iします(ゼロから始まる場合、4倍するとゼロのままになりますが、アイテム0は空白なので、Iインクリメントされます)。

上記の定数「4」を他の数値に置き換えることができることに注意してください。一般に、値が大きいほど作業のタグ付けは少なくなりますが、値が小さいほど作業のクリアは少なくなります。タグ付きのアレイスロットはクリアする必要があるため、3または4の値がほぼ確実に最適です。値4は確かに最適値に近く、2または8よりも優れており、他のどの数値よりも便利であるため、最も合理的な選択と思われます。


すべてのセルが新しい値で更新される前に、十分な順次リセットに対応できるバージョンカウンタがあれば十分です。実際には、1バイトで十分かもしれませんし、よりタイトなループではさらに少ないかもしれません。
9000

@ 9000:そのような振る舞いに依存するコードは、特に「配列をクリアするのではなく」そのような「疑似クリア」アプローチを使用する唯一の理由が、必要なアイテムのセットがクリアされるのは、通常、小さくて可変でした。アイテムが使用され、「クリア」され、任意の長い間触れられないままになる可能性を高めるために共謀する条件のペアです。カウンターがラップするときにアレイをスキャンし、古いスロットを物理的にクリアすることを検討できますが、
...-supercat

1
...カウンターの折り返し値が一定の場合、各配列クリア操作の平均作業量はO(N)になり、Nは配列のサイズになります。65,536の係数で高速化されたO(N)実装は依然としてO(N)であるが、改善されていない実装の65,536倍の速さであるため、そのようなことは実際には役に立たない可能性はありません。ちなみに、これらのアプローチが役立つ場合は、O(AlgN)スペースを使用してサイズNの配列とAの非空白要素を保持できるスパース配列データ構造を使用することも有益です。
-supercat

1

私はそれを「遅延配列セルの再初期化」と呼びますが、確立された名前(つまり、広く使用されている名前)はないようです。

アルゴリズムは巧妙ですが、非常に特殊化されており、非常に狭い領域に適用できます。


1

これはメモ化の特別なケースだと思いますが、この場合、グローバルカウンタの増分ごとに暗黙的に「メモ」が「年齢」になることを除きます。私は一種の「後方のメモ化」を推測します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.