2016-11-18 20 views
1

最近、インタビューで、このノードクラスを与えられたツリー内のすべてのノードを数えるように求められました。私はインタビューの中で、脳のおならを持っていたもののツリー内のノードを再帰的にカウントしない。

class Node 
{ 
    public List<Node> Children; 
} 

iは再帰的にそれをしない数分で今朝これを書きました。

int CountNodes(Node node, int count) 
{ 
    count++; 

    if(node.Children == null) 
     return count; 

    foreach(Node n in node.Children) 
    { 
     count = CountNodes(n, count); 
    } 

    return count; 
} 

しかし、会話中に私たちは再帰的アプローチで問題を議論しました。 1つはスタックオーバーフローです。

これを解決するには、非再帰的な方法は何でしょうか。私はそれに苦しんでいるようだ。

+1

だから、あなたが実装しました[深さ優先検索](https://en.wikipedia.org/wiki/Depth-first_search) - 代わりに[幅優先検索](https://en.wikipedia.org/wiki/Breadth-first_search)です。 )、これは基本的に[tail tail recursion](https://en.wikipedia.org/wiki/Tail_call)です。最後に、 'Node'の実装を制御すると、(ルート上に)子が追加されたときに' Node'インスタンスの子カウンタをインクリメントすることもできます。 –

+0

一般的な方法は、キューを使用することです。アルゴリズムは簡単です:まず、ルートノードを追加します。次に、キューが空ではない間:デキューし、その上で何らかの操作を実行し、そのすべての子をキューに追加して繰り返します。 –

答えて

2

すべてのルートノードを含むList<Node> nodesから始めることができます。この方法は、ノードが存在しなくなるまでループだろう「現在」レベルに残され、各繰り返しで、そのレベルの子供たちと一緒にnodesリストを置き換える:

List<Node> nodes = GetRootNodes(); 
int total = 0; 
while (nodes.Count > 0) 
{ 
    total += nodes.Count; 
    List<Node> children = new List<Node>(); 
    foreach (Node node in nodes) 
    { 
     children.AddRange(node.Children); 
    } 

    nodes = children; 
} 
+1

[幅優先検索](https://en.wikipedia.org/wiki/Breadth-first_search)はそのための技術的な用語です:) –

2

Breadth-first search

int CountNodes(Node node) 
{ 
    int count = 0; 
    List<Node> nodesToSearch = new List<Node>(); 
    nodesToSearch.Add(node); 

    while(nodesToSearch.Count > 0){ 
     count += nodesToSearch.Count; 

     List<Node> newNodes = new List<Node>(); 
     foreach(Node nodeToSearch in nodesToSearch){ 
      if(nodeToSearch.Children != null) 
       newNodes.AddRange(nodeToSearch.Children); 
     } 
     nodesToSearch = newNodes; 
    } 

    return count; 
} 
+0

いいえ、あなたはカウントを返し、nodeToSearch.Childrenがnullであることを確認する必要があります。しかし、それは動作します。 – CathalMF

+1

Tnx、それを修正しました.. – GregaMohorko

関連する問題