[Structure des données] Implémentation chaînée et parcours d'arbres binaires


Insérer la description de l'image ici

1. Parcours d'arbre binaire

Les nœuds de l'arbre binaire dans tous les codes ci-dessous :

typedef char BTDataType;
//二叉树结点结构体
typedef struct BinaryTreeNode
{
    
    
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

1. Parcours de précommande

Les parcours de précommande, intermédiaire et post-commande peuvent tous être résolus en utilisant l'idée de récursion diviser pour régner, et le nœud racine et ses nœuds enfants sont traités séparément.

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    printf("%c ", root->data);
    BinaryTreePrevOrder(root->left);
    BinaryTreePrevOrder(root->right);
}

Ici, nous utilisons uniquement le graphe d'expansion récursif pour analyser le parcours en pré-ordre. La même idée est utilisée en ordre et en post-ordre :

Insérer la description de l'image ici

Insérer la description de l'image ici

2. Parcours dans l'ordre

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreeInOrder(root->left);
    printf("%c ", root->data);
    BinaryTreeInOrder(root->right);
}

3. Parcours post-commande

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreePostOrder(root->left);
    BinaryTreePostOrder(root->right);
    printf("%c ", root->data);
}

4. Traversée séquentielle des couches

Le parcours d'ordre de niveau doit être effectué à l'aide d'une file d'attente. Si l'arbre binaire et le nœud ne sont pas vides, laissezmettre en file d'attente un pointeur vers celui-ci, puis enregistrez le nœud de tête de la file d'attente, imprimez d'abord sa valeur, puis jugez que ses enfants gauche et droit ne sont pas vides puis rejoignez la file d'attente, puis supprimez la tête de la file d'attente et remplacez-la par le suivant pour continuer l'enregistrement et impression... jusqu'à ce que la file d'attente soit vide et que le parcours soit terminé.

Par exemple, considérons cet arbre binaire comme indiqué :

Le résultat du parcours de la séquence de couches est : 12345.
Insérer la description de l'image ici
Tout d’abord, placez le nœud racine 1 dans la file d’attente et imprimez 1.

Insérer la description de l'image ici

Ajoutez ensuite les enfants gauche et droit 2 et 3 sur 1 dans l'équipe
Insérer la description de l'image ici

Supprimez le début de la file d'attente 1, remplacez front par 2 et imprimez 2
Insérer la description de l'image ici

Ajoutez ensuite l'enfant de gauche 4 sur 2 à l'équipe
Insérer la description de l'image ici

Supprimez la tête 2, remplacez le devant par 3 et imprimez 3
Insérer la description de l'image ici

Ajoutez ensuite le bon enfant 5 sur 3 à l'équipe
Insérer la description de l'image ici

… …

Imprimez ensuite 4 et 5 comme ceci pour terminer le parcours par ordre de niveau de l'arbre binaire.

Insérer la description de l'image ici

Le code du programme utilise la file d'attente créée par lui-même. Le code est le suivant :

//层序遍历
void LevelOrder(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        //将队头打印
        BTNode* front = QueueFront(&q);
        printf("%c ", front->data);
        //判断front左右节点不为空则入队
        if (front->left)
            QueuePush(&q, front->left);

        if (front->right)
            QueuePush(&q, front->right);
        
        QueuePop(&q);
    }
    printf("\n");

    QueueDestroy(&q);
}

2. Nombre et hauteur des nœuds de l'arbre binaire

1. Nombre de nœuds d'arbre binaire

Il est implémenté de manière récursive à l'aide de la méthode diviser pour régner. Lorsque le nœud racine est vide, la valeur de retour est 0. S'il n'est pas vide, il renvoie le nombre de nœuds sur les sous-arbres gauche et droit plus 1.

int BinaryTreeSize(BTNode* root)
{
    
    
    return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

2. Nombre de nœuds feuilles de l'arbre binaire

Il est implémenté de manière récursive à l'aide de la méthode diviser pour régner. Lorsque le nœud racine est vide, 0 est renvoyé. Lorsque le nœud racine n'a pas de nœud enfant, cela signifie qu'il s'agit d'un nœud feuille et 1 est renvoyé. Dans d'autres cas, ajoutez simplement les nœuds feuilles sur les sous-arbres gauche et droit.

int BinaryTreeLeafSize(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return 0;
    }
    if (root->left == NULL && root->right == NULL)
    {
    
    
        return 1;
    }
    return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

3. Nombre de nœuds au kème niveau de l'arbre binaire

Vous devez vous assurer que k est supérieur à 0. Lorsque le nœud racine est vide, 0 est renvoyé. Lorsque k est égal à 1, il n'y a qu'un seul nœud dans une couche et 1 est renvoyé. Lorsque k>1, le nombre Le nombre de nœuds dans la kème couche équivaut au kème enfant de ses enfants gauche et droit.-Le nombre de nœuds dans la couche 1 est additionné.

int BinaryTreeLevelKSize(BTNode* root, int k)
{
    
    
    assert(k > 0);

    if (root == NULL)
    {
    
    
        return 0;
    }
    if (k == 1)
    {
    
    
        return 1;
    }
    return BinaryTreeLevelKSize(root->left, k - 1)
        + BinaryTreeLevelKSize(root->right, k - 1);
}

4. Trouvez le nœud de valeur x dans un arbre binaire

Si le nœud suivant est vide, NULL est renvoyé s'il est introuvable. Lorsque la valeur du nœud racine est la valeur que vous recherchez, le nœud est renvoyé. S'ils ne sont pas égaux, ses nœuds enfants gauche et droit sont jugés. respectivement jusqu'à ce qu'ils soient trouvés.

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
    
    
    if (root == NULL)
    {
    
    
        return NULL;
    }
    if (root->data == x)
    {
    
    
        return root;
    }
    BTNode* ret = BinaryTreeFind(root->left,x);
    if (ret)
    {
    
    
        return ret;
    }
    return BinaryTreeFind(root->right, x);
}

3. Création et destruction d'arbre binaire

1. Créez un arbre binaire en parcourant le tableau en précommande

Lisez une chaîne de parcours de précommande saisie par l'utilisateur et créez un arbre binaire (stocké sous forme de pointeur) basé sur cette chaîne. Par exemple, la chaîne de parcours de précommande suivante : ABC##DE#G##F### où "#" représente un espace et le caractère espace représente une arborescence vide. Après avoir établi l'arbre binaire, effectuez un parcours dans l'ordre sur l'arbre binaire et affichez les résultats du parcours.

#include <stdio.h>
#include<stdlib.h>
typedef char BTDataType;

typedef struct BinaryTreeNode {
    
    
    BTDataType data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
} BTNode;
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
    
    
    if (a[*pi] == '#') {
    
    
        ++*pi;
        return NULL;
    }

    BTNode* root = (BTNode*)malloc(sizeof(BTDataType));
    root->data = a[*pi];
    ++*pi;

    root->left = BinaryTreeCreate(a, pi);
    root->right = BinaryTreeCreate(a, pi);

    return root;
}
//中序遍历
void InOrder(BTNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return;
    }
    InOrder(root->left);
    printf("%c ",root->data);
    InOrder(root->right);
}
int main() {
    
    
    char a[100];
    scanf("%s",a);
    int pi=0;
    BTNode* root=BinaryTreeCreate(a, &pi);
    InOrder(root);
    return 0;
}

2. Destruction des arbres binaires

void BinaryTreeDestory(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }

    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    free(root);
}

3. Déterminez s'il s'agit d'un arbre binaire complet

Modifiez le parcours au niveau de l'ordre de l'arbre binaire afin que les nœuds vides entrent également dans la file d'attente. Lors du parcours d'un nœud vide, il sortira. S'il y a des nœuds non vides avant la fin du parcours, ce n'est pas un arbre binaire complet.

int BinaryTreeComplete(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front == NULL)
        {
    
    
            break;
        }
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
        QueuePop(&q);
    }
    //此时已经遇到空节点,如果再遇到非空节点则不是完全二叉树
    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front)
        {
    
    
            QueueDestroy(&q);
            return false;
        }
        QueuePop(&q);
    }

    QueueDestroy(&q);
    return true;
}

4. Tester le code

Construisez manuellement un arbre binaire comme indiqué ci-dessous et testez le code :
Insérer la description de l'image ici
le résultat du test doit être :

Précommande : 123874569
Séquence intermédiaire : 832715469
Postcommande : 837259641

S'il s'agit d'un arbre binaire complet : 0
Nombre de nœuds : 9
Nombre de nœuds feuilles : 4

BTNode* BuyNode(BTDataType x)
{
    
    
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if (node == NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }

    node->data = x;
    node->left = NULL;
    node->right = NULL;

    return node;
}


int main()
{
    
    
    	// 手动构建
	BTNode* node1 = BuyNode('1');
	BTNode* node2 = BuyNode('2');
	BTNode* node3 = BuyNode('3');
	BTNode* node4 = BuyNode('4');
	BTNode* node5 = BuyNode('5');
	BTNode* node6 = BuyNode('6');
	BTNode* node7 = BuyNode('7');
	BTNode* node8 = BuyNode('8');
	BTNode* node9 = BuyNode('9');

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	node2->right = node7;
	node3->left = node8;
	node6->right = node9;

    printf("前序遍历:");
    BinaryTreePrevOrder(node1);
	printf("\n");

    printf("中序遍历:");
    BinaryTreeInOrder(node1);
	printf("\n");

    printf("后序遍历:");
    BinaryTreePostOrder(node1);
	printf("\n");

    printf("层序遍历:");
    LevelOrder(node1);
    printf("\n");

    printf("BinaryTreeComplete:%d\n", BinaryTreeComplete(node1));
    printf("BinaryTreeSize:%d\n", BinaryTreeSize(node1));
    printf("BinaryTreeLeafSize:%d\n", BinaryTreeLeafSize(node1));

    BinaryTreeDestory(node1);
	node1 = NULL;

    return 0;
}

résultat de l'opération :

Insérer la description de l'image ici
Les résultats d'exécution sont conformes aux résultats prévus.

Je suppose que tu aimes

Origine blog.csdn.net/zcxyywd/article/details/133107365
conseillé
Classement