143 votes

Quand utiliser les stratégies de parcours d'arbre de recherche binaire préordonnée, postordonnée et inordonnée ?

J'ai réalisé récemment que, bien qu'ayant utilisé les BST à de nombreuses reprises dans ma vie, je n'ai jamais envisagé d'utiliser autre chose que la traversée d'ordre (bien que je sois conscient et sache à quel point il est facile d'adapter un programme pour utiliser la traversée de pré/post-ordre).

Lorsque je m'en suis rendu compte, j'ai ressorti mes vieux manuels sur les structures de données et j'ai cherché le raisonnement qui sous-tend l'utilité des traversées avant et après l'ordre - ils ne disaient pas grand-chose cependant.

Quels sont les exemples de cas où il convient d'utiliser pratiquement la précommande ou la post-commande ? Quand est-ce plus logique que l'ordre interne ?

184voto

Eric Leschinski Points 14289

Quand utiliser la stratégie d'annulation des commandes préalables, des commandes en cours et des commandes ultérieures ?

Avant de comprendre dans quelles circonstances il convient d'utiliser le pré-ordre, l'ordre interne et le post-ordre pour un arbre binaire, vous devez comprendre exactement comment chaque stratégie de traversée fonctionne. Prenons l'exemple de l'arbre suivant.

La racine de l'arbre est 7 le nœud le plus à gauche est 0 le nœud le plus à droite est 10 .

enter image description here

Traversée d'un ordre préalable :

Résumé : Commence à la racine ( 7 ), se termine au nœud le plus à droite ( 10 )

Séquence de navigation : 7, 1, 0, 3, 2, 5, 4, 6, 9, 8, 10

Traversée dans l'ordre :

Résumé : commence au nœud le plus à gauche ( 0 ), se termine au nœud le plus à droite ( 10 )

Séquence d'inversion : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Traversée post-ordre :

Résumé : commence par le nœud le plus à gauche ( 0 ), se termine par la racine ( 7 )

Séquence d'inversion : 0, 2, 4, 6, 5, 3, 1, 8, 10, 9, 7

Quand utiliser Pré-commande, En cours de commande ou Post-commande ?

La stratégie de traversée choisie par le programmeur dépend des besoins spécifiques de l'algorithme en cours de conception. L'objectif étant la rapidité, choisissez la stratégie qui vous permet d'accéder le plus rapidement aux nœuds dont vous avez besoin.

  1. Si vous savez que vous devez explorer les racines avant d'inspecter les feuilles, vous choisissez précommande car vous rencontrerez toutes les racines avant toutes les feuilles.

  2. Si vous savez que vous devez explorer toutes les feuilles avant les nœuds, vous sélectionnez post-ordre car vous ne perdez pas de temps à inspecter les racines à la recherche de feuilles.

  3. Si vous savez que l'arbre a une séquence inhérente dans les nœuds, et que vous voulez aplatir l'arbre pour lui redonner sa séquence d'origine, alors une commande en ordre doit être utilisé. L'arbre sera aplati de la même manière qu'il a été créé. Un parcours avant ou après l'ordre peut ne pas ramener l'arbre dans la séquence qui a été utilisée pour le créer.

Algorithmes récursifs pour le préordre, l'ordre interne et l'ordre externe (C++) :

struct Node{
    int data;
    Node *left, *right;
};
void preOrderPrint(Node *root)
{
  print(root->name);                                  //record root
  if (root->left != NULL) preOrderPrint(root->left);  //traverse left if exists
  if (root->right != NULL) preOrderPrint(root->right);//traverse right if exists
}

void inOrderPrint(Node *root)
{
  if (root.left != NULL) inOrderPrint(root->left);   //traverse left if exists
  print(root->name);                                 //record root
  if (root.right != NULL) inOrderPrint(root->right); //traverse right if exists
}

void postOrderPrint(Node *root)
{
  if (root->left != NULL) postOrderPrint(root->left);  //traverse left if exists
  if (root->right != NULL) postOrderPrint(root->right);//traverse right if exists
  print(root->name);                                   //record root
}

79voto

Viraj Nimbalkar Points 471

Pré-commande : Permet de créer une copie d'un arbre. Par exemple, si vous souhaitez créer une réplique d'un arbre, placez les nœuds dans un tableau avec un parcours préalable. Ensuite, effectuez un Insérer sur un nouvel arbre pour chaque valeur du tableau. Vous obtiendrez une copie de votre arbre original.

En commande : : Utilisé pour obtenir les valeurs des nœuds dans un ordre non décroissant dans une BST.

Après la commande : : Utilisé pour supprimer un arbre de la feuille à la racine.

29voto

Oli Charlesworth Points 148744

Si je voulais simplement imprimer le format hiérarchique de l'arbre dans un format linéaire, j'utiliserais probablement la traversée avant ordre. Par exemple :

- ROOT
    - A
         - B
         - C
    - D
         - E
         - F
             - G

5voto

Raphael Points 1262

Le pré- et le post-ordre se rapportent respectivement aux algorithmes récursifs descendants et ascendants. Si vous souhaitez écrire un algorithme récursif donné sur des arbres binaires de manière itérative, c'est ce que vous ferez essentiellement.

Observez en outre que les séquences de pré- et de post-ordre spécifient complètement l'arbre en question, ce qui donne un encodage compact (pour les arbres clairsemés au moins).

3voto

Il y a des tas d'endroits où cette différence joue un rôle réel.

J'en citerai un excellent : la génération de code pour un compilateur. Prenons l'exemple de l'énoncé suivant :

x := y + 32

La façon de générer du code pour cela est (naïvement, bien sûr) de générer d'abord du code pour charger y dans un registre, charger 32 dans un registre, et ensuite générer une instruction pour additionner les deux. Parce que quelque chose doit se trouver dans un registre avant que vous ne le manipuliez (supposons que vous puissiez toujours utiliser des opérandes constants, mais peu importe), vous devez procéder de cette manière.

En général, les réponses à cette question se résument à ceci : la différence est vraiment importante lorsqu'il existe une certaine dépendance entre le traitement des différentes parties de la structure de données. C'est le cas lors de l'impression des éléments, lors de la génération de code (l'état externe fait la différence, vous pouvez bien sûr considérer cela de manière monadique), ou lorsque vous effectuez d'autres types de calculs sur la structure qui impliquent des calculs dépendant des enfants qui sont traités en premier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X