誰かがコード、擬似コード、またはプレーンJavaScript(JQueryやヘルパーライブラリなし)でDFSとBFSを実装するための適切なリンクを提供できますか?どちらのトラバーサルを実装するかを理解しようとしていますが、BFSとDFSの実装の違いを実際に区別できないようです。
例として具体的な問題が必要な場合:特定のノードでDOMをトラバースし、すべてのクラス名を取得します。
(トラバースすることを考える唯一の方法は、各親ノードを通過し、そのノードから必要なものを取得することです。この例ではクラス名です。次に、子があるかどうかを確認し、子ごとに繰り返します。これはDFSだと思います。繰り返しますが、DOMトラバーサル実装の違いを理解するのに苦労しています!)
最後に、これが繰り返しの場合は申し訳ありません。私はどこでも良い、明確な例を探しましたが、素晴らしい答えは見つかりませんでした!そこにすでに良い答えがある場合は、私に知らせてください:)
例として次のHTMLコードを使用してみましょう。
<div class="a">
<div class="aa">
<span class="aaa">
</span>
<span class="aab">
</span>
</div>
<div class="ab">
<span class="aba">
</span>
<span class="abb">
</span>
</div>
</div>
DFSは常に最初に次のレベルのノードに移動し、トラバースされていない子ノードがなくなった場合にのみ、現在のレベルの次のノードに移動します。
DFSは、次の順序で例のノードをトラバースします。
a, aa, aaa, aab, ab, aba, abb
BFSは常に最初に現在のレベルのすべてのノードをトラバースし、その後でのみ次のレベルのノードに移動します。
BFSは、次の順序で例のノードをトラバースします。
a, aa, ab, aaa, aab, aba, abb
これらのどれを使用すべきか明確な答えはありません。通常、それはあなたのニーズに依存します。
実装の詳細:
DFSの場合、人々はしばしば stack を使用します。
擬似コード:
stack my_stack;
list visited_nodes;
my_stack.Push(starting_node);
while my_stack.length > 0
current_node = my_stack.pop();
if current_node == null
continue;
if current_node in visited_nodes
continue;
visited_nodes.add(current_node);
// visit node, get the class or whatever you need
foreach child in current_node.children
my_stack.Push(child);
このコードは、スタックにノードが存在するまで続きます。各ステップで、スタックの最上位ノードを取得します。それがnullでない場合、および以前にアクセスしたことがない場合は、アクセスしてすべての子をスタックに追加します。
Queue は通常BFSに使用されます。
擬似コード:
queue my_queue;
list visited_nodes;
my_queue.enqueue(starting_node);
while my_queue.length > 0
current_node = my_queue.dequeue();
if current_node == null
continue;
if current_node in visited_nodes
continue;
visited_nodes.add(current_node);
// visit node, get the class or whatever you need
foreach child in current_node.children
my_queue.enqueue(child);
このコードは、キューにノードが存在するまで続きます。各ステップで、キューの最初のノードを取得します。それがnullでない場合、および以前にアクセスしたことがない場合は、アクセスしてすべての子をキューに追加します。
2つのアルゴリズムの主な違いは、使用するデータ型であることに注意してください。
DFS:
function m(elem) {
elem.childNodes.forEach(function(a) {
m(a);
});
//do sth with elem
}
m(document.body);
これはすべての要素をループし、各要素については各子などをループします。
BFS:
var childs = [];
function m(elem) {
elem.childNodes.forEach(function(a) {
childs.Push(a);
});
b = childs;
childs = [];
b.forEach(function(a) {
m(a);
});
}
m(document.body);
これは要素をループし、子をスタックにプッシュし、各要素から再開します。ご覧のとおり、これははるかに多くのスペース(子の配列)を消費しますが、これは最善ではありません...
DFSの場合、 TreeWalker または NodeIterator APIを使用し、NodeFilter.SHOW_ELEMENT
でフィルタリングできます。