2016-08-12 11 views
-1

下記のメソッドの実装方法を理解するのに問題があります。ツリーに値が含まれているかどうかを調べるために深さの最初の検索を使用しようとしていますが、私の実装に何が問題なのかよく分かりません。私はこれを行うとき最大コールスタックサイズを超えました。ロジックが間違っている箇所を特定できない

class Tree { 
    constructor(val) { 
    this.value = val; 
    this.children = []; 
    } 

    addChild(val) { 
    this.children.push(new Tree(val)); 
    } 

    contains(val) { 
    if (this.value === val) { 
     return true; 
    } else if (this.children.length > 0) { 
     for (var i = 0; i < this.children.length; i++) { 
     this.contains(this.children[i].contains(value)); 
     } 
     // When it gets to the leaf node, how do I go back to the previous call? 
     // Do I need to return something here? 
    } 

    return false; // I may be incorrect on this, but it should return false (execute this line) only when every node has been visited, and there are no more nodes to check. 
    } 
}; 

だから:

const T = new Tree(100); 
T.addChild(50); 
T.addChild(40); 
T.children[0].addChild(3); 

console.log(T.contains(40)); 

は私があるため、最大コールスタックエラーのうちエラー。

+1

実際に 'contains()'の中にあるループの中で 'contains()'を2回呼び出すと推測していますが、貧弱なブラウザではあまりにも多くなります – adeneo

答えて

3

この行:containsはブール値を返す必要がありますように、それは木がそのブール値が含まれている場合は、再度チェックしても意味がありませんので、

this.contains(this.children[i].contains(value)); 

は疑問です。また、この行には問題があります。つまり、containsと全く同じ引数(thisを引数とします)を呼び出しているため、停止しないため、「最大呼び出しスタックサイズを超えました」というエラーが発生します - スタックオーバーフロー。

代わりに、あなたはこれにそれを変更する必要があります。

if (this.children[i].contains(value)) 
    return true; 

そのように、それは価値を見つけた最初の時間は、それが返されます。再帰は、の基底ケースを持っているので、つまりthis.childrenの値を見つけるか、ループの終わりから落ちるため、期待通りに機能します。

+0

@rvignhne "あなたは、 (これを引数とみなして)まったく同じ引数で呼び出します。つまり、決して停止しないで、 "最大呼び出しスタックサイズを超過しました"というエラー - 別名スタックオーバーフローです。 " – AlanH

+0

@AlanH 'this'で' contains'を呼び出しているので、意図したようにツリーの次のレベルをチェックしていません。代わりに、ツリーの同じレベルをブール値(2番目のコールを含む)からチェックしています。 'children'がブール値を含んでいなければ、' contains'はそれを見つけられませんが、それを見つけようとしている無制限のコピーを生成し、最終的にスタックオーバーフローを引き起こします。 [この質問](http://stackoverflow.com/questions/717725/understanding-recursion)再帰のいくつかの良い例があります。 – rvighne

関連する問題