質問

次のようなツリーを指定しました:

http://www.seqan.de/dddoc/html/streePreorder.png http://www.seqan.de/dddoc/html/streePreorder.png

iは、次の演算子を使用して各ノードにアクセスできます。

// postorder dfs
Iterator< Index<String<char> >, BottomUp<> >::Type myIterator(myIndex);
for (; !atEnd(myIterator); goNext(myIterator)) 
    // do something with myIterator

しかし、ツリーで再帰アルゴリズムを使用したい。
再帰アルゴリズム(各ノードの最大のサブツリーを除く)を反復的に実行する方法はありますか?
またはどのようにして非再帰的に要素にアクセスできますか?

編集: 実際の問題:
木で動作する再帰アルゴリズムを指定しました。 (再帰的)
また、アイテムにイテレータ(非標準、反復)のみをアクセスできるライブラリを使用しています

再帰<!> lt;-<!> gt;反復。
どうすれば解決できますか?

役に立ちましたか?

解決

イテレータが順方向(および場合によっては逆方向)のトラバーサルのみをサポートし、ツリーまたは高速ランダムアクセスのリンクをたどらない場合、ツリーアルゴリズムをそれに適応させるのは非常に困難になります。ただし、最終的には、回答はカスタムイテレータによって提供されるインターフェイスに依存しますが、これは提供していません。

たとえば、ツリー検索の簡単なアルゴリズムを考えてみましょう。イテレータによって指定された唯一の操作が<!> quot;最初の要素から開始して1つずつ<!> quot;に移動する場合、ツリー検索を効率的に実装できないことは明らかです。また、バイナリ検索を実装することもできません。そのため、サポートされている操作の正確なリストと、(厳密には)各操作の複雑さの範囲を指定する必要があります。

他のヒント

スタックの助けを借りて、再帰関数を反復関数に変換できます。

//breadth first traversal pseudo-code
push root to a stack
while( stack isn't empty )
    pop element off stack
    push children
    perform action on current node

ノードをどのようにトラバースするかによって、実装は異なります。すべての再帰関数は反復関数に変換できます。一般的な使用方法では、特定の問題に関する情報が必要です。スタック/キューの使用とforループへの変換は、ほとんどの状況を解決する一般的な方法です。

これらの問題はforループにうまく変換されるため、多くのコンパイラーがあなたのためにこれを行います。

一部のより数学的に指向した再帰呼び出しは、再帰関係によって解決できます。まだ解決されていないこれらに出くわす可能性は低いですが、興味があるかもしれません。

// edit、パフォーマンス? 実装とツリーのサイズに本当に依存します。再帰呼び出しに多くの深度がある場合、スタックオーバーフローが発生しますが、反復バージョンでは問題なく実行されます。再帰(メモリの使用方法)をよりよく把握でき、状況に適した方を判断できるはずです。 フィボナッチ数によるこのタイプの分析の例

代わりに、任意の再帰関数をスタックで実装できます。これがあなたが尋ねている質問である場合。

この件に関する Phil Haackによる記事があります。

パフォーマンスはいずれかの方法で推測されますが、コンパイラーは、常に予測できるとは限らない舞台裏のコードで処理を行います。両方を実装し、実数を取得します。似ている場合は、読みやすいものを使用してください。

繰り返しを繰り返しても、ノードごとの訪問になります。

知っておく必要があるのは、どのようにイテレータに深さ優先を指示し、次に1つのレベルが開始/終了したかを通知する方法です(つまり、再帰ステップの開始/終了)。

その知識は再帰アルゴリズムにマッピングできます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top