web-dev-qa-db-fra.com

Comment imprimeriez-vous les données dans une arborescence binaire, niveau par niveau, en commençant par le haut?

Ceci est une question d'entrevue

Je pense à une solution. Il utilise la file d'attente.

public Void BFS()    
{   
   Queue q = new Queue();    
   q.Enqueue(root);    
   Console.WriteLine(root.Value);  

   while (q.count > 0)  
   {  
      Node n = q.DeQueue();  
      if (n.left !=null)  
       {  
          Console.Writeln(n.left);  
          q.EnQueue(n.left);  
        }   
       if (n.right !=null)  
       {  
          Console.Writeln(n.right);  
          q.EnQueue(n.right);  
        }   
    }
}    

Rien ne peut penser à une meilleure solution que celle-ci, qui n’utilise pas Queue?

17
Learner

La traversée de niveau en niveau est appelée largeur-première traversée. Utiliser une file d’attente est la bonne façon de procéder. Si vous vouliez faire une première traversée en profondeur, vous utiliseriez une pile.

La façon dont vous l’avez n’est pas tout à fait standard cependant. Voici comment cela devrait être.

public Void BFS()    
{      
 Queue q = new Queue();
 q.Enqueue(root);//You don't need to write the root here, it will be written in the loop
 while (q.count > 0)
 {
    Node n = q.DeQueue();
    Console.Writeln(n.Value); //Only write the value when you dequeue it
    if (n.left !=null)
    {
        q.EnQueue(n.left);//enqueue the left child
    }
    if (n.right !=null)
    {
       q.EnQueue(n.right);//enque the right child
    }
 }
}

Modifier

Voici l'algorithme au travail. Disons que vous avez un arbre comme ceci:

     1
    / \
   2   3
  /   / \
 4   5   6

Premièrement, la racine (1) serait mise en file d'attente. La boucle est ensuite entrée. Le premier élément de la file d'attente (1) est retiré de la file d'attente et imprimé. Les enfants de 1 sont mis en file d'attente de gauche à droite, la file d'attente contient maintenant {2, 3} retour au début de la boucle le premier élément de la file (2) est mis en file d'attente et imprimé. Les enfants de 2 sont mis en file d'attente de gauche à droite. La file contient maintenant {3, 4} retour au début de la boucle ...

La file d'attente contiendra ces valeurs sur chaque boucle

1: {1}

2: {2, 3}

3: {3, 4}

4: {4, 5, 6}

5: {5, 6}

6: {6}

7: {} // vide, la boucle se termine

Sortie:

1

2

3

4

5

6

38
CodeFusionMobile

Étant donné que la question nécessite d’imprimer l’arborescence niveau par niveau, il doit exister un moyen de déterminer quand imprimer le nouveau caractère de ligne sur la console. Voici mon code qui tente de faire la même chose en ajoutant un noeud NewLine à la file d'attente,

void PrintByLevel(Node *root)
{
   Queue q;
   Node *newline = new Node("\n");
   Node *v;
   q->enque(root);
   q->enque(newline);

   while(!q->empty()) {
      v = q->deque();
      if(v == newline) {
         printf("\n");
         if(!q->empty())
            q->enque(newline);
      }
      else {
         printf("%s", v->val);
         if(v->Left)
            q-enque(v->left);
         if(v->right)
            q->enque(v->right);
      }
   }
   delete newline;
}
16
Mru

Voyons quelques solutions Scala. Premièrement, je vais définir un arbre binaire très basique:

case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])

Nous allons utiliser l'arbre suivant:

    1
   / \
  2   3
 /   / \
4   5   6

Vous définissez l'arbre comme ceci:

val myTree = Tree(1, 
                  Some(Tree(2, 
                            Some(Tree(4, None, None)), 
                            None
                       )
                  ),
                  Some(Tree(3,
                            Some(Tree(5, None, None)),
                            Some(Tree(6, None, None))
                       )
                  )
             )

Nous allons définir une fonction widththFirst qui traversera l’arbre en appliquant la fonction souhaitée à chaque élément. Avec cela, nous allons définir une fonction d'impression et l'utiliser comme ceci:

def printTree(tree: Tree[Any]) = 
  breadthFirst(tree, (t: Tree[Any]) => println(t.value))

printTree(myTree)

Maintenant, la solution Scala, récursive, liste mais pas de files d'attente:

def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
  def traverse(trees: List[Tree[T]]): Unit = trees match {
    case Nil => // do nothing
    case _ =>
      val children = for{tree <- trees
                         Some(child) <- List(tree.left, tree.right)} 
                         yield child
      trees map f
      traverse(children)
  }

  traverse(List(t))
}

Ensuite, solution Scala, file d'attente, pas de récursivité:

def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
  import scala.collection.mutable.Queue
  val queue = new Queue[Option[Tree[T]]]
  import queue._

  enqueue(Some(t))

  while(!isEmpty) 
    dequeue match {
      case Some(tree) => 
        f(tree)
        enqueue(tree.left)
        enqueue(tree.right)
      case None =>
    }
}

Cette solution récursive est pleinement fonctionnelle, même si j'ai le sentiment qu'il est possible de la simplifier davantage.

La version de la file d’attente n’est pas fonctionnelle, mais elle est très efficace. Le point relatif à l'importation d'un objet est inhabituel dans Scala, mais il est utile de l'utiliser ici.

5
Daniel C. Sobral

C++:

  struct node{
    string key;
    struct node *left, *right;
  };

  void printBFS(struct node *root){
    std::queue<struct node *> q;
    q.Push(root);

    while(q.size() > 0){
      int levelNodes = q.size();
      while(levelNodes > 0){
        struct node *p = q.front(); 
        q.pop();
        cout << " " << p->key ;
        if(p->left != NULL) q.Push(p->left);
        if(p->right != NULL) q.Push(p->right);
        levelNodes--;
      }
      cout << endl;
    }
  }

Entrée:

Arbre équilibré créé à partir de:

 string a[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"};

Sortie:

 g 
 c k 
 a e i m 
 b d f h j l n 

Algorithme:

  1. Créez une liste de tableaux de noeuds de liste liée. 
  2. Effectuez la traversée de niveaux en utilisant la file d'attente (largeur d'abord). 
  3. Pour obtenir tous les nœuds à chaque niveau, avant de retirer un nœud de la file d'attente, stockez la taille de la file d'attente dans une variable, par exemple, appelez-la sous le nom levelNodes. 
  4. Maintenant que levelNodes> 0, sortez les nœuds, imprimez-les et ajoutez leurs enfants dans la file d'attente. 
  5. Après cette boucle while, mettez un saut de ligne.

P.S: Je sais que l'OP a dit, pas de file d'attente. Ma réponse consiste simplement à indiquer si quelqu'un recherche une solution C++ utilisant la file d'attente.

4
kaushal
public class LevelOrderTraversalQueue {     

    Queue<Nodes> qe = new LinkedList<Nodes>();

    public void printLevelOrder(Nodes root)     
    { 
        if(root == null) return;

        qe.add(root);
        int count = qe.size();

        while(count!=0)
        {   
            System.out.print(qe.peek().getValue());
            System.out.print("  ");
            if(qe.peek().getLeft()!=null) qe.add(qe.peek().getLeft());
            if(qe.peek().getRight()!=null) qe.add(qe.peek().getRight());
            qe.remove(); count = count -1;
            if(count == 0 )
            {
                System.out.println("  ");
                count = qe.size();
            }
        }           
    }

}
2
anshu

Afin d'imprimer par niveau, vous pouvez stocker les informations de niveau avec le nœud sous forme de tuple à ajouter à la file d'attente. Vous pouvez ensuite imprimer une nouvelle ligne chaque fois que le niveau est modifié. Voici un code Python pour le faire.

from collections import deque
class BTreeNode:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

    def printLevel(self):
        """ Breadth-first traversal, print out the data by level """
        level = 0
        lastPrintedLevel = 0
        visit = deque([])
        visit.append((self, level))
        while len(visit) != 0:
            item = visit.popleft()
            if item[1] != lastPrintedLevel:  #New line for a new level
                lastPrintedLevel +=1
                print
            print item[0].data,
            if item[0].left != None:
                visit.append((item[0].left, item[1] + 1))
            if item[0].right != None: 
                visit.append((item[0].right, item[1] + 1))
1
Faruk Sahin

Bien sûr, vous n'avez pas besoin d'utiliser la file d'attente. Ceci est en python.

# Function to  print level order traversal of tree
def printLevelOrder(root):
    h = height(root)
    for i in range(1, h+1):
        printGivenLevel(root, i)


# Print nodes at a given level
def printGivenLevel(root , level):
    if root is None:
        return
    if level == 1:
        print "%d" %(root.data),
    Elif level > 1 :
        printGivenLevel(root.left , level-1)
        printGivenLevel(root.right , level-1)


""" Compute the height of a tree--the number of nodes
    along the longest path from the root node down to
    the farthest leaf node
"""
def height(node):
    if node is None:
        return 0
    else :
        # Compute the height of each subtree 
        lheight = height(node.left)
        rheight = height(node.right)
        return max(lheight, reight)
0
Aerin

Je pense que ce que vous attendez est d’imprimer les nœuds à chaque niveau, séparés par un espace ou une virgule et les niveaux séparés par une nouvelle ligne. Voici comment je coderais l'algorithme. Nous savons que lorsque nous effectuons une recherche approfondie sur un graphique ou une arborescence et que nous insérons les noeuds dans une file d'attente, tous les noeuds de la file d'attente sortant seront au même niveau que le précédent ou un nouveau niveau qui est le niveau parent +1 et rien d'autre. 

Ainsi, lorsque vous êtes à un niveau, continuez d’imprimer les valeurs des nœuds et dès que vous constatez que le niveau du nœud augmente de 1, vous insérez une nouvelle ligne avant de commencer à imprimer tous les nœuds de ce niveau. 

C'est mon code qui n'utilise pas beaucoup de mémoire et seule la file d'attente est nécessaire pour tout. 

En supposant que l'arbre commence à la racine. 

queue = [(root, 0)]  # Store the node along with its level. 
prev = 0
while queue:
  node, level = queue.pop(0)
  if level == prev:
    print(node.val, end = "")
  else:
    print()
    print(node.val, end = "")
  if node.left:
    queue.append((node.left, level + 1))
  if node.right:
    queue.append((node.right, level + 1))
  prev = level

À la fin, tout ce dont vous avez besoin est la file d’attente pour tous les traitements. 

0
Ankur Kothari

Essayez avec le code ci-dessous.

public void printLevelOrder(TreeNode root) {
    if (root == null) {
        return;
    }
    Queue<TreeNode> nodesToVisit = new LinkedList<>();
    nodesToVisit.add(root);

    int count = nodesToVisit.size();

    while (count != 0) {
        TreeNode node = nodesToVisit.remove();

        System.out.print(" " + node.data);

        if (node.left != null) {
            nodesToVisit.add(node.left);
        }

        if (node.right != null) {
            nodesToVisit.add(node.right);
        }

        count--;

        if (count == 0) {
            System.out.println("");
            count = nodesToVisit.size();
        }
    }
}
0
Naren

J'ai peaufiné la réponse pour qu'elle affiche les nœuds nuls et l'imprime en hauteur. Était en fait assez convenable pour tester l'équilibre d'un arbre noir rouge. pouvez
ajoute également la couleur dans la ligne d'impression pour vérifier la hauteur du noir. 

    Queue<node> q = new Queue<node>();
    int[] arr = new int[]{1,2,4,8,16,32,64,128,256};
    int i =0;
    int b = 0;
    int keeper = 0;
    public void BFS()
    {


        q.Enqueue(root);
        while (q.Count > 0)
        {

            node n = q.Dequeue();

            if (i == arr[b])
            {

                System.Diagnostics.Debug.Write("\r\n"+"("+n.id+")"); 
                b++;
                i =0 ;
            }
            else {

                System.Diagnostics.Debug.Write("(" + n.id + ")"); 

            }
            i++; 


            if (n.id != -1)
            {



                if (n.left != null)
                {

                    q.Enqueue(n.left);
                }
                else
                {
                    node c = new node();
                    c.id = -1;
                    c.color = 'b';
                    q.Enqueue(c);
                }

                if (n.right != null)
                {

                    q.Enqueue(n.right);
                }
                else
                {
                    node c = new node();
                    c.id = -1;
                    c.color = 'b';
                    q.Enqueue(c);

                }
            }

        }
        i = 0;
        b = 0;
        System.Diagnostics.Debug.Write("\r\n");
    }
0
Travis Halvorson

Essayez celui-ci (code complet): 

class HisTree
{
    public static class HisNode
    {
        private int data;
        private HisNode left;
        private HisNode right;

        public HisNode() {}
        public HisNode(int _data , HisNode _left , HisNode _right)
        {
            data = _data;
            right = _right;
            left = _left;
        }
        public HisNode(int _data)
        {
            data = _data;
        }
    }

    public static int height(HisNode root)
    {
        if (root == null)
        {
            return 0;
        }

        else
        {
            return 1 + Math.max(height(root.left), height(root.right));
        }
    }


    public static void main(String[] args)
    {
//          1
//         /  \ 
//        /    \
//       2      3
//      / \    / \  
//     4    5 6   7
//    /
//   21

        HisNode root1 = new HisNode(3 , new HisNode(6) , new HisNode(7));
        HisNode root3 = new HisNode(4 , new HisNode(21) , null);
        HisNode root2 = new HisNode(2 , root3 , new HisNode(5));
        HisNode root = new HisNode(1 , root2 , root1);
        printByLevels(root);
    }


    private static void printByLevels(HisNode root) {

        List<HisNode> nodes = Arrays.asList(root);
        printByLevels(nodes);

    }

    private static void printByLevels(List<HisNode> nodes)
    {
        if (nodes == null || (nodes != null && nodes.size() <= 0))
        {
            return;
        }
        List <HisNode> nodeList = new LinkedList<HisNode>();
        for (HisNode node : nodes)
        {
            if (node != null)
            {
                System.out.print(node.data);
                System.out.print(" , ");
                nodeList.add(node.left);
                nodeList.add(node.right);
            }
        }
        System.out.println();
        if (nodeList != null && !CheckIfNull(nodeList))
        {
            printByLevels(nodeList);    
        }
        else
        {
            return;
        }

    }


    private static boolean CheckIfNull(List<HisNode> list)
    {
        for(HisNode elem : list)
        {
            if (elem != null)
            {
                return false;
            }
        }
        return true;
    }
}
0
ron