3

私は matlab のツリーで再帰呼び出しを使用しています。関数の基本構造は次のとおりです。

function recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       recursion(tree.child(j).targetedFeatures)
    end
end

ツリーの構造は次のようになります。

            root
           /  |  \
          /   |   \
         /    |    \
      leaf1  leaf2  leaf3

関数再帰の入力パラメーターは、targetedFeatures という名前のベクトルで、その初期値が [0 0 0] であると仮定します。リーフ 1 にアクセスする過程で、ベクトルは [1 0 0] に変更されますが、リーフ 2 にアクセスすると、targetedFeature [0 0 0] に戻りました

matlabのベクトルが他のプログラミング言語のオブジェクトへの参照を好まないためだと思いますか?

この問題を回避するにはどうすればよいですか? ありがとう。

4

3 に答える 3

2

Matlab は、通常の型の変数に値による呼び出しを使用します。こちらを参照してください。これを回避する方法は、関数が変更されたコピーを出力引数として返すようにすることです。

function targetedFeatures = recursion(tree, targetedFeatures)
  ...
  targetedFeatures = recursion(tree.child(j).targetedFeatures);
  ...
end

代わりに、参照渡しは and を使用してシミュレートできevalin('caller', ...)ますinputname

于 2013-10-28T19:19:38.070 に答える
1

recursion関数が を変更する必要がある場合、その関数呼び出しに対してローカルtargetedFeaturesな のコピーが作成されます。targetedFeatures更新を呼び出しスコープに送り返したい場合はtargetedFeatures、関数から更新を返す必要があります。

function targetedFeatures = recursion(tree, targetedFeatures)

    if (some conditions fulfilled)
      return;
    end

    for i = 1:1:size(targetedFeatures,2)
      .....
      .....
       if (some conditions that using index i is true)
          targetedFeatures(1,i) = 1; 
       end
    end

    if(tree has child nodes)
       targetedFeatures = recursion(tree.child(j).targetedFeatures)
    end
end

これは、たとえば C で行うようなポインタ操作ほど効果的ではありませんが、 を更新するたびにローカル コピーを作成しているため、コードが既に実行していることに大きなパフォーマンス ヒットが見られることはありませんtargetedFeatures

コピー オン ライト メカニズムについて説明しているこの投稿へのリンクを提供してくれた chappjc に感謝します。

于 2013-10-28T19:22:09.960 に答える
0

ツリーの長さと最終的には深さに応じて、上記のリターンベースのソリューションはすぐにかなり醜くなります。原則として、多くのリーフの1つだけを変更したいのに、常にルートノードを変更する必要があるためです。

代わりに、TreeNode オブジェクトのハンドル クラスの実装を検討することをお勧めします。これは、次のような単純なものから始まります。

classdef TreeNode < handle

    properties
        targetedFeatures;
        child; % vector keeping handles to TreeNode children
        parent; % handle of the parent node, of which this node is a child
    end

    methods
        ...
    end
end

明らかに、子などを追加/削除するメソッドを入力する必要があります。このようなツリーを使用すると、最上位のルートノードへの参照を常に持ち歩く必要なく、最も深いリーフまで再帰してその値を変更できます。これを配置したら、変更せずに関数を使用できるはずです。

MATLAB のドキュメントで示されているリンク リスト用のクラスは、多少似たクラスの実装です: http://www.mathworks.de/de/help/matlab/matlab_oop/example--implementing-linked-lists.html親と複数の子ではなく、前と次の「子」がありますが、一般的な構造はかなり似ています。

ノードの追加/削除、検索など、このツリーで他の多くの操作を行う予定がある場合は、ある時点で間違いなく価値があります。たまたまそのツリーに出くわし、この 1 つの問題を修正しただけで作業が完了した場合は、返品ベースのソリューションを選択してください。

于 2013-10-29T07:47:38.310 に答える