web-dev-qa-db-fra.com

Traversée en largeur d'abord

J'essayais de résoudre une question d'entrevue, mais pour cela, je dois parcourir l'arbre binaire niveau par niveau. J'ai conçu BinaryNode avec une variable ci-dessous

private object data;
private BinaryNode left;
private BinaryNode right;

Quelqu'un pourrait-il aider à écrire la méthode BreadthFirstSearch dans ma classe BinarySearchTree?

Mise à jour: Merci à tous pour vos contributions. C'était donc la question de l'entretien. "Étant donné un arbre de recherche binaire, concevez un algorithme qui crée une liste chaînée de tous les nœuds à chaque profondeur (c'est-à-dire, si vous avez un arbre de profondeur D, vous aurez des listes chaînées D)".

Voici ma méthode, faites-moi savoir votre commentaire d'expert.

public List<LinkedList<BNode>> FindLevelLinkList(BNode root)
    {
        Queue<BNode> q = new Queue<BNode>();
        // List of all nodes starting from root.
        List<BNode> list = new List<BNode>();
        q.Enqueue(root);
        while (q.Count > 0)
        {
            BNode current = q.Dequeue();
            if (current == null)
                continue;
            q.Enqueue(current.Left);
            q.Enqueue(current.Right);
            list.Add(current);
        }

        // Add tree nodes of same depth into individual LinkedList. Then add all LinkedList into a List
        LinkedList<BNode> LL = new LinkedList<BNode>();
        List<LinkedList<BNode>> result = new List<LinkedList<BNode>>();
        LL.AddLast(root);
        int currentDepth = 0;
        foreach (BNode node in list)
        {
           if (node != root)
            {
                if (node.Depth == currentDepth)
                {
                    LL.AddLast(node);
                }
                else
                {
                    result.Add(LL);
                    LL = new LinkedList<BNode>();
                    LL.AddLast(node);
                    currentDepth++;
                }
            }
        }

        // Add the last linkedlist
        result.Add(LL);
        return result;
    }
37
Pritam Karmakar

Une première recherche étendue est généralement implémentée avec un file d'attente, une première recherche approfondie utilisant un pile.

Queue<Node> q = new Queue<Node>();
q.Enqueue(root);
while(q.Count > 0)
{
    Node current = q.Dequeue();
    if(current == null)
        continue;
    q.Enqueue(current.Left);
    q.Enqueue(current.Right);

    DoSomething(current);
}

Au lieu de vérifier null après la mise en file d'attente, vous pouvez vérifier avant d'ajouter à la file d'attente. Je n'ai pas compilé le code, il peut donc contenir de petites erreurs.


Une version plus sophistiquée (mais plus lente) qui s'intègre bien avec LINQ:

public static IEnumerable<T> BreadthFirstTopDownTraversal<T>(T root, Func<T, IEnumerable<T>> children)
{
    var q = new Queue<T>();
    q.Enqueue(root);
    while (q.Count > 0)
    {
        T current = q.Dequeue();
        yield return current;
        foreach (var child in children(current))
            q.Enqueue(child);
    }
}

Qui peut être utilisée avec une propriété Children sur Node:

IEnumerable<Node> Children { get { return new []{ Left, Right }.Where(x => x != null); } }

...

foreach(var node in BreadthFirstTopDownTraversal(root, node => node.Children))
{
   ...
}
69
CodesInChaos
var queue = new Queue<BinaryNode>();
queue.Enqueue(rootNode);

while(queue.Any())
{
  var currentNode = queue.Dequeue();
  if(currentNode.data == searchedData)
  {
    break;
  }

  if(currentNode.Left != null)
    queue.Enqueue(currentNode.Left);

  if(currentNode.Right != null)
    queue.Enqueue(currentNode.Right);
}
13
Viacheslav Smityukh