再帰を使用せずにn
-aryツリーをトラバースするにはどうすればよいですか?
再帰的な方法:
traverse(Node node)
{
if(node == null)
return;
for(Node child : node.getChilds()) {
traverse(child);
}
}
これは、再帰やスタックなしで実行できます。ただし、ノードに2つのポインタを追加する必要があります。
現在の子ノードなので、次に取るノードがわかります。
擬似コードを使用すると、次のようになります。
traverse(Node node) {
while (node) {
if (node->current <= MAX_CHILD) {
Node prev = node;
if (node->child[node->current]) {
node = node->child[node->current];
}
prev->current++;
} else {
// Do your thing with the node.
node->current = 0; // Reset counter for next traversal.
node = node->parent;
}
}
}
あなたがしているのは本質的にツリーのDFSです。スタックを使用すると、再帰を排除できます。
traverse(Node node) {
if (node==NULL)
return;
stack<Node> stk;
stk.Push(node);
while (!stk.empty()) {
Node top = stk.pop();
for (Node child in top.getChildren()) {
stk.Push(child);
}
process(top);
}
}
BFSが必要な場合は、キューを使用します。
traverse(Node node) {
if (node==NULL)
return;
queue<Node> que;
que.addRear(node);
while (!que.empty()) {
Node front = que.deleteFront();
for (Node child in front.getChildren()) {
que.addRear(child);
}
process(front);
}
}
他の方法でトラバースする場合は、ノードを格納するためのデータ構造が異なりますが、同じアプローチに従う必要があります。おそらく優先度付きキュー(各ノードで関数を評価し、その値に基づいてノードを処理する場合)。
言語が指定されていないため、疑似擬似コードでは次のようになります。
traverse(Node node)
{
List<Node> nodes = [node];
while (nodes.notEmpty) {
Node n = nodes.shift();
for (Node child in n.getChildren()) {
nodes.add(child);
}
// do stuff with n, maybe
}
}
これは、質問で指定された深さ優先トラバーサルとは対照的に、幅優先トラバーサルであることに注意してください。最初のアイテムをpop
する代わりに、nodes
リストの最後のアイテムをshift
することで、深さ優先探索を実行できるはずです。