前提
再帰を使ったDFSはスタックに書き換えることができるそうですが、再帰の戻り値を使ったDFSをスタックによるDFSへの書き換え方がわかりません。
C++
1// 適当な例です 2struct node 3{ 4 int value; 5 node *left; 6 node *right; 7}; 8 9int dfs( node *n ) 10{ 11 if( n == nullptr ) 12 return INT_MIN; 13 14 int left_value = dfs( n->left ); 15 int right_value = dfs( n->left ); 16 17 return max( n->value, max( left_value, right_value )); 18}
例えばこのようなグラフ探索のコードがあるとします。左右の子ノードを探索し、自身の値を含めた3つの中で最大の値を呼び出し元に返すことを意識しています。
これをスタック変数を使って書き換えると次のようになると思ったのですが
C++
1int main() 2{ 3 struct node 4 { 5 int value; 6 node *left; 7 node *right; 8 }; 9 10 stack<node> s; 11 node n; 12 s.push(n); 13 14 while( !s.empty() ) 15 { 16 n = s.top(); 17 s.pop(); 18 19 if( n == nullptr ) 20 continue; // 次の状態をスタックに積まずにループを周回する 21 22 s.push(n->left); 23 s.push(n->right); 24 } 25}
この2つは動作が同じではないように思います。
再帰を使ったものは、A -> B -> Cという順で呼び出した場合にA -> B -> C -> B -> Aという順で遷移します。Bで再帰関数を呼び出した際にBの動作は一旦停止し、Cが終わってからBの続きをします。ですからBでCの結果を利用することができます。
しかしスタック変数の場合はループの中でスタックに積みますが、実際にノードを探索するのは次のループでスタックからpopしたときです。BでCをスタックに積みますが、Bが終わって次のループの冒頭でCがスタックからポップされます。ですから、BでCの結果を利用することはできないように思います。
これは例ですので、単に全ノードで一番大きな値が欲しいだけなら、どこかスコープの外で変数を宣言し、そこに格納すればいいのですが、細部で異なります。
DFSの場合は困ったら再帰でいいのですが、スタック変数とループの場合はスタックをキューに変更すれば、BFSに直せる点でメリットがあると考えています。
実現したいこと
再帰を使ったDFSを、スタック変数とループを使った等価なDFSに書き換えたい。
例えば
https://leetcode.com/problems/binary-tree-maximum-path-sum/
この問題を再帰を使わないで解きたい。
補足情報(FW/ツールのバージョンなど)
よろしくお願いします。

回答2件
あなたの回答
tips
プレビュー