[Structure des données et algorithme] Traversée d'arbre binaire facile à comprendre

Dans l'explication facile à comprendre des arbres de recherche binaires (veuillez me pousser), l'article présente principalement la nature des arbres de recherche binaires. Cet article continuera à présenter la traversée des arbres binaires.

Traversée de l'arbre de recherche binaire

Traverser tous les nœuds de l'arbre n'est à visiter qu'une seule fois. Selon la position du nœud racine, il est principalement divisé en traversée de pré-ordre, traversée d'ordre moyen et traversée de post-ordre. Notez que le parcours de l'arbre de recherche binaire et de l'arbre binaire ordinaire est exactement le même, donc dans ce qui suit, il n'est pas distingué s'il s'agit d'un arbre de recherche binaire ou d'un arbre binaire.

Parcours de précommande

L'opération de traversée de précommande d'un arbre binaire est la suivante:

  • Visitez le nœud racine
  • La précommande traverse le sous-arbre de gauche
  • La précommande traverse le bon sous-arbre

Par exemple, dans la figure suivante, l'ordre d'accès au nœud de traversée des pré-ordres de l'arbre binaire est 3 1 2 5 4 6:
[Structure des données et algorithme] Traversée d'arbre binaire facile à comprendre
Selon les étapes de fonctionnement de la traversée des pré-ordres analysées ci-dessus, il n'est pas difficile de voir qu'il est facile d'implémenter l'accès aux précommandes de l'arbre binaire par méthode récursive:

//前序遍历递归版本
void preOrder(struct node *root)
{
    if(root != NULL)
    {
        cout << root->data << " ";
        preOrder(root->left);
        preOrder(root->right);
    }
}

En fait, le parcours de précommande de l'arbre binaire peut également être implémenté de manière non récursive: puisque le nœud racine doit être récupéré après avoir traversé le nœud racine afin de parcourir le bon sous-arbre correspondant au nœud racine, vous pouvez envisager d'utiliser la pile pour stocker le Le nœud racine de l'implémentation du code est le suivant:

//前序遍历的非递归版本
void preOrder(struct node *root)  
{  
    stack<struct node *> s;  
    while (root != NULL || !s.empty()) 
    {  
        if (root != NULL) 
        {  
        //访问结点并入栈
            cout << root->data << " ";   
            s.push(root);                
            root = root->left; //访问左子树  
       } 
       else 
       {  
            root = s.top();  //回溯至父亲结点  
            s.pop();  
            root = root->right; //访问右子树  
       }  
    }  
    cout << endl;  
}  

Traversée dans l'ordre

L'opération de traversée d'ordre intermédiaire d'un arbre binaire est la suivante:

  • Traversée d'ordre moyen du sous-arbre gauche
  • Visitez le nœud racine
  • Traversée d'ordre intermédiaire du sous-arbre droit

Par exemple, dans la figure suivante, l'ordre d'accès des nœuds dans le parcours de l'arbre binaire est 1 2 3 4 5 6:
[Structure des données et algorithme] Traversée d'arbre binaire facile à comprendre

Comme le parcours de précommande, il peut également être implémenté de manière récursive ou non récursive, et l'idée est similaire, sauf que l'ordre d'accès est différent. Les deux implémentations sont les suivantes:

//中序遍历递归版本
void inOrder(struct node *root)
{
    if(root != NULL)
    {
        inOrder(root->left);
    //和前序遍历相比,只是输出语句换了个位置唯一
    cout << root->data << " ";
        inOrder(root->right);
    }
}
//中序遍历的非递归版本
void inOrder(struct node *root)  
{  
    stack<struct node *> s;  
    while (root != NULL || !s.empty()) 
    {  
        if (root != NULL) 
        {  
            s.push(root);  
            root = root->left;  
        }  
        else 
        {  
        //访问完左子树后才访问根结点  
            root = s.top();  
            cout << root->data << " ";  
            s.pop();  
            root = root->right; //访问右子树  
        }  
    }  
    cout << endl;  
}  

Traversée ultérieure

L'opération de traversée post-ordre d'un arbre binaire est la suivante:

  • Traversée post-ordre du sous-arbre gauche
  • Traversée post-ordre du sous-arbre droit
  • Visitez le nœud racine

Par exemple, dans la figure suivante, l'ordre d'accès aux nœuds de traversée post-ordre de l'arbre binaire est 2 1 4 6 5 3: La
[Structure des données et algorithme] Traversée d'arbre binaire facile à comprendre
version récursive du parcours post-ordre de l'arbre binaire est similaire à l'ordre intermédiaire de pré-ordre, comme suit:

//后序遍历递归版本
void postOrder(struct node *root)
{
    if(root != NULL)
    {
        postOrder(root->left);
        postOrder(root->right);

        //最后访问根节点
        cout << root->data << " ";
    }
}

L'algorithme non récursif de traversée post-ordre est plus compliqué et peut être implémenté en utilisant une seule pile, mais le processus est très lourd. Nous pouvons envisager d'utiliser deux piles pour implémenter l'algorithme non récursif de traversée post-ordre. Notez que le parcours post-ordre peut être considéré comme le processus inverse du parcours suivant: c'est-à-dire, traverser d'abord un certain nœud, puis traverser son enfant droit, puis traverser son enfant gauche. L'inverse de ce processus est la traversée post-ordre. Les étapes de l'algorithme sont les suivantes:

(1) Poussez le nœud racine vers la première pile.
(2) Pop un nœud de la pile et le pousser vers la sortie de la pile.
(3) Poussez ensuite l'enfant gauche et l'enfant droit du nœud vers la première pile s.
(4) Répétez les procédures 2 et 3 jusqu'à ce que la pile soit vide.
(5) Maintenant, tous les nœuds ont été poussés vers la sortie de la pile, et stockés dans l'ordre de traversée post-ordre, et pop out directement est le résultat de la traversée post-ordre de l'arbre binaire.

Le code est implémenté comme suit:

//后序遍历的非递归版本
void postOrder(struct node *root)  
{  
    if (!root) return;  
    stack<struct node*> s, output;  
    s.push(root);  
    while (!s.empty()) 
    {  
        struct node *curr = s.top();  
        output.push(curr);  
        s.pop();  
        if (curr->left)  
            s.push(curr->left);  
        if (curr->right)  
            s.push(curr->right);  
    }  

    while (!output.empty()) 
    {  
        cout << output.top()->data << " ";  
        output.pop();  
    }  
    cout << endl;  
}  

Lecture recommandée:

[Bien-être] Partage vidéo de cours de boutique en ligne collectés par moi-même (
Partie 1 ) [Conception du système] Cache LRU
[Structure des données et algorithme] Liste chaînée facile à comprendre
[Structure des données et algorithme] Tri de bits facile à comprendre
[Notes C ++] C ++ 11 Programmation simultanée (1) Démarrer le parcours des threads
[Notes C ++] Pièges courants dans l'utilisation des pointeurs C / C ++
[Notes C ++] Explication détaillée des bibliothèques statiques et dynamiques (on)

Focus sur le partage de résumé des connaissances de la pile de technologie d'arrière-plan du serveur

Bienvenue à prêter attention à la communication et au progrès commun

[Structure des données et algorithme] Traversée d'arbre binaire facile à comprendre

Codage

Le fermier de code a la bonne façon de vous fournir des articles techniques faciles à comprendre pour faciliter la technologie!

Je suppose que tu aimes

Origine blog.51cto.com/15006953/2552022
conseillé
Classement