arbre binaire -print les éléments en fonction du niveau

voix
6

Cette question m'a été posée dans une interview:

arbre

permet de dire que nous avons au-dessus de l'arbre binaire, comment puis-je produire une sortie comme ci-dessous

2 7 5 2 6 9 5 11 4

Je lui ai répondu que peut-être que nous pouvons avoir une variable de comptage de niveau et d'imprimer tous les éléments de manière séquentielle en vérifiant la variable de comptage de niveau de chaque nœud. probablement que j'avais tort.

quelqu'un peut-il donner anyidea à la façon dont nous pouvons atteindre cet objectif?

Créé 14/04/2011 à 08:07
source utilisateur
Dans d'autres langues...                            


7 réponses

voix
2

Le traversal dans votre question est appelé level-order traversalet c'est la façon dont il est fait (extrait de code très simple , / j'ai trouvé propre).

Vous utilisez essentiellement une file d'attente et l'ordre des opérations ressemblera à quelque chose comme ceci:

enqueue F
dequeue F
enqueue B G
dequeue B
enqueue A D
dequeue G
enqueue I
dequeue A
dequeue D
enqueue C E
dequeue I
enqueue H
dequeue C
dequeue E
dequeue H

Pour cet arbre (de Wikipedia droite):
entrez la description d'image ici

Créé 14/04/2011 à 08:14
source utilisateur

voix
2

Le terme qui est le niveau d'ordre traversal . Wikipedia décrit un algorithme pour qu'utiliser une file d' attente :

levelorder(root) 
  q = empty queue
  q.enqueue(root)
  while not q.empty do
    node := q.dequeue()
    visit(node)
    if node.left ≠ null
      q.enqueue(node.left)
    if node.right ≠ null
      q.enqueue(node.right)
Créé 14/04/2011 à 08:14
source utilisateur

voix
2

BFS :

std::queue<Node const *> q;
q.push(&root);
while (!q.empty()) {
    Node const *n = q.front();
    q.pop();
    std::cout << n->data << std::endl;
    if (n->left)
        q.push(n->left);
    if (n->right)
        q.push(n->right);
}

Itératives approfondissement collaborerait également et enregistre l'utilisation de la mémoire, mais au détriment du temps de calcul.

Créé 14/04/2011 à 08:16
source utilisateur

voix
6

Vous devez faire une première largeur traversal de l'arbre. Ici , il est décrit comme suit:

Parcours en largeur: profondeur d'abord n'est pas la seule façon de passer par les éléments d'un arbre. Une autre façon est de passer par les niveau par niveau.

Par exemple, chaque élément existe à un certain niveau (ou profondeur) dans l'arbre:

    tree
      ----
       j         <-- level 0
     /   \
    f      k     <-- level 1
  /   \      \
 a     h      z  <-- level 2
  \
   d             <-- level 3

Les gens aiment les choses numéro commençant par 0)

Donc, si nous voulons visiter le niveau par niveau (et de gauche à droite, comme d'habitude) éléments, nous commencerions au niveau 0 avec j, puis passer au niveau 1 pour f et k, puis passer au niveau 2 pour, h et z, et enfin passer au niveau 3 pour d.

Ce niveau par niveau traversal est appelé un parcours en largeur parce que nous explorons la largeur, à savoir, largeur de l'arbre à un niveau donné, avant d'aller plus loin.

Créé 14/04/2011 à 08:16
source utilisateur

voix
0

J'utiliser une collection, par exemple std::list, pour stocker tous les éléments du niveau en cours d' impression:

  1. Recueillir des pointeurs vers tous les nœuds du niveau actuel dans le conteneur
  2. Imprimer les noeuds répertoriés dans le conteneur
  3. Faire un nouveau conteneur, ajoutez les sous-noeuds de tous les noeuds dans le conteneur
  4. Ecraser l'ancien conteneur avec le nouveau conteneur
  5. répéter jusqu'à ce que le contenant est vide
Créé 14/04/2011 à 08:18
source utilisateur

voix
0

comme un exemple de ce que vous pouvez faire à une entrevue si vous ne vous souvenez pas / ne connaissent pas l'algorithme « officiel », ma première idée était - traverse l'arbre dans le pré-ordre régulier faisant glisser un compteur de niveau le long, le maintien d'un vecteur des listes liées de pointeurs vers des noeuds par niveau, par exemple

levels[level].push_back(&node);

et à la fin imprimer la liste de chaque niveau.

Créé 14/04/2011 à 08:39
source utilisateur

voix
2

Si nous sommes en mesure d'aller chercher l'élément suivant au même niveau, nous fait. Selon notre connaissance préalable , nous pouvons accéder à ces éléments en utilisant la largeur première traversal.

Maintenant, seul problème est de savoir comment vérifier si nous sommes le dernier élément à tout niveau. Pour cette raison, nous devrions être l'ajout d'un séparateur (NULL dans ce cas) pour marquer la fin d'un niveau.

Algorithme: 1. Mettez racine dans la file d' attente.
2. NULL Mettre en file d' attente.
3. Alors que la file d' attente ne soit pas vide
4. x = chercher premier élément de file d' attente
5. Si x est NULL
6. X-> rpeer <= élément supérieur de la file d' attente.
7. mettre l' enfant à gauche et à droite de x dans la file d' attente
8. autre
9. si la file d' attente n'est pas vide
10. NULL mettre en file d' attente
11. fin si
12. fin en
13. retour

#include <queue>

void print(tree* root)
{
  queue<tree*> que;
  if (!root)
      return;

  tree *tmp, *l, *r;
  que.push(root);
  que.push(NULL);

  while( !que.empty() )
  {
      tmp = que.front();
      que.pop();
      if(tmp != NULL)
      {
          cout << tmp=>val;  //print value
          l = tmp->left;
          r = tmp->right;
          if(l) que.push(l);
          if(r) que.push(r);
      }
      else
      {
          if (!que.empty())
              que.push(NULL);
      }
  }
  return;
}
Créé 14/04/2011 à 11:55
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more