IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

création d'un arbre binaire


Sujet :

C

  1. #1
    Membre actif
    Femme Profil pro
    Enseignant
    Inscrit en
    Août 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2012
    Messages : 71
    Par défaut création d'un arbre binaire
    bonsoir;
    je veux utiliser le principe de création d'arbre binaire pour créer un arbre binaire de recherche,
    le principe c'est que j'ai une valeur seuil=4, et un tableau contenant des valeurs de type réel, je veux créer l'arbre en comparant chaque valeur du tableau avec la valeur du seuil, si la valeur du tableau est inférieure au seuil, alors on ajoute l'indice tab[1] coté gauche sinon on l'ajoute coté droit, et ainsi de suite; sachant que la racine doit contenir l'indice tab[0].

    voici un exemple d'arbre:
    Nom : arbre.png
Affichages : 1219
Taille : 15,2 Ko

    exemple de code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    #include <stdlib.h>
    # include <stdio.h>
     
    /* 
       On définit un type pour les éléments et une fonction de comparaison
       entre éléments 
    */
    typedef double element_t;
     
    int comparer(element_t a){
      if (a < 4) return 1;
      if (a > 4) return -1;
      return 0;
    }
     
    void affiche_element(element_t a) {
      printf("%g ", a);
    }
    /*
      On définit le type des arbres binaires, qui est utilisé ici pour
      les arbres binaires de recherche (voir cours).
     
      L'arbre vide est représenté par NULL (l'adresse mémoire 0).
    */
     
    typedef struct noeud_s {
      element_t        e;
      struct noeud_s * gauche;
      struct noeud_s * droite;
      struct noeud_s * parent;
    } * ab_t;
     
     
    /* nouveau_noeud(a), crée (allocation mémoire) et renvoie un arbre à
       un seul noeud contenant l'élément a. */
     
    ab_t nouveau_noeud(element_t a){
      ab_t x;
      x = malloc(sizeof(ab_t*));
      if (!x) {
        perror("Echec malloc");
      }
      x->parent = NULL;
      x->gauche = NULL;
      x->droite = NULL;
      x->e = a;
      return x;
    }
     
    /* inserer(&x, a) insere un élément a dans un arbre binaire de
       recherche x. S'il existe déjà un élément b égal à a dans l'arbre
       aucun noeud n'est créé (pas de répétition).  La fonction inserer()
       ne renvoie rien, l'arbre x est passé par adresse (px = adresse de
       l'arbre) pour être directement modifié (argument-résultat). */ 
     
    void inserer(ab_t *px, element_t a){
      if (!(*px)) {
        *px = nouveau_noeud(a);
      }  
      else {
        ab_t y, parent;
        int cote;
        y = *px;
        /* Recherche de la place de a (parent et côté où le mettre) */
        while (y) {
          parent = y;
          cote = comparer(a);
          switch(cote){
          case 1: /* côté gauche */
            y = y->gauche;
            break;
          case -1: /* côté droit */ 
            y = y->droite;
            break;
          case 0: /* on a déjà cet élément, pas d'insertion */
            return;       
          }    
        }
        /* parent sera le parent du nouveau noeud, la valeur de cote dit
           de quel côté l'attacher à son parent.  */
        y = nouveau_noeud(a);
        y->parent = parent;
        if (1 == cote) {
          parent->gauche = y;
        }
        else {
          parent->droite = y;
        }
      }    
    }
     
     
    /* vider(&x) : libère l'espace mémoire utilisé par l'arbre x, et met x
       à NULL (arbre vide) */
     
    void vider(ab_t *px){
      ab_t x;
      x = *px;
      if (x) {
        vider(&(x->gauche));
        vider(&(x->droite));
        free(x);
        *px = NULL;
      }
    }
     
     
    /* fonction auxilliaire pour l'affichage d'une ligne de traits
       verticaux représentant la descendance à gauche. */
     
    void afficher_arbre_aux1(ab_t x){
      if (x->parent) {
        afficher_arbre_aux1(x->parent);
        if (x == (x->parent)->droite) {
          if ((x->parent)->gauche) {
            printf(" |      "); /* 8 caractères */
          }
          else {
            printf("        "); /* 8 caractères */
          }
        }
      }
    }
     
    /* afficher_arbre(x) réalise l'affichage de x sur la sortie standard
       comme décrit plus haut. */
     
    void afficher_arbre(ab_t x){
      if (x) { /* Si l'arbre n'est pas vide, on réalise l'affichage par
                  appels récursifs sur les sous-arbres non vides. */
     
        affiche_element(x->e);
        if (x->droite) { /* noeuds de droite sur la même ligne */
          printf("-----");
          afficher_arbre(x->droite);
        }
        else { /* plus rien à droite : fin de ligne */
        printf("\n");
        }
        if (x->gauche) {   
          afficher_arbre_aux1(x->gauche);
          printf(" |      \n"); /* 8 caractères */
          afficher_arbre_aux1(x->gauche);
          afficher_arbre(x->gauche);
        }
      }
      else { /* Si l'arbre est vide on le signale */
        printf("\n        (arbre vide)\n\n");
      }
    }
     
     
    int main() {
        ab_t            x = NULL;
        //element_t       i;
        int i;
     
        element_t       tab[] = {0.7, 0.8, 6.7, 6, 7, 8.3, 9, 7.6};
     
        for (i = 0; i < 8; i++) {
         inserer(&x, tab[i]);
        }
     
     
        afficher_arbre(x);
     
      system("PAUSE");	
      return EXIT_SUCCESS;
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 747
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 747
    Par défaut
    c'est quoi la question le code ne me semble pas incorrect (en regardant d'1 œil et de travers)

    Par contre, ton dessin est faux (* ->) Dans un arbre binaire de recherche, chaque nœud à exactement 2 fils sinon c'est une feuille (binaire veut dire 2, c'est fou )
    Et c'est le tri par tas qui crée un arbre binaire de recherche avec un tableau C. Justement, grâce à sa propriété (*) on peut déduire (si je ne me trompe pas )
    • le père de la case X : si X pair, père == tab[X / 2], sinon père == (tab[X / 2] - 1)
    • les 2 fils de la case X : fils gauche (2X + 1), fils droit 2(X + 1)


    Après vérifications, dans une arbre binaire, 1 nœud peut avoir 1 seul fils ma propriété (*) correspond à un "full/ strict binary tree" (notamment les AVL). Et pour associer un arbre à un tableau C, il faut que l'arbre soit complet ("complete binary tree") soit parfait ("perfect binary tree")

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Ton problème majeur, c'est que tu compares à une valeur hard-codée.
    Tu dois comparer chaque nœud à la valeur recherchée (ou celle que tu veux ajouter, conceptuellement c'est la même chose)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre actif
    Femme Profil pro
    Enseignant
    Inscrit en
    Août 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2012
    Messages : 71
    Par défaut
    Bonjour;
    je suis tout à fait d'accord avec vous , mais le travail que je dois réaliser c'est d'utiliser le même principe des arbres binaires pour transformer une matrice en un arbre, pour une classification des données, et je dois comparer la valeur du seuil avec chaque valeur de la matrice, dans ce cas la, les nœuds représentent des indices et les arcs les valeurs de la matrice

    matrice.doc

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 801
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Déjà cacher l'étoile derrière un type est une très mauvaise pratique. D'une part parce que ça ne la fait pas disparaitre (elle apparait toujours quand tu as un double pointeur il en reste une) et surtout ça entraine ensuite des confusions par exemple quand tu écris ab_t x = malloc(sizeof(ab_t*)) (réfléchis 5 secondes et si tu trouves pas, réécris la même ligne en remplaçant "ab_t" par son type !!!).

    Et ensuite je ne m'explique pas ta fonction "inserer" qui crée 2 noeuds. Accessoirement, si tu réfléchis là aussi 5 secondes supplémentaires, tu te rendras compte qu'elle n'a même pas besoin de recevoir l'adresse du noeud venu du main (elle peut très bien créer elle-même le noeud en local et l'insérer à sa bonne place).
    Et enfin créer le type "t_arbre" dédié à l'arbre. Ca aide d'avoir un truc pour tenir l'arbre. Même s'il n'a comme contenu que le noeud racine c'est par grave, déjà ça aide à la programmation en évitant ce double étoile obligatoire pour une fonction qui aurait à modifier la racine et aussi ça ouvre la voie à des améliorations futures). Ainsi la fonction d'insertion reçoit cet arbre en en paramètre ainsi que le noeud à insérer et n'a plus qu'à trouver où va le noeud.

    Et surtout arrête de planquer tes étoiles comme si tu en avais peur.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    #include <stdlib.h>
    # include <stdio.h>
     
    /* 
    	 On définit un type pour les éléments et une fonction de comparaison
    	 entre éléments 
    */
    typedef double element_t;
     
    int comparer(element_t a, int v){
    	if (a < v) return 1;
    	if (a > v) return -1;
    	return 0;
    }
     
    void affiche_element(element_t a) {
    	printf("%g ", a);
    }
     
    typedef struct noeud_s {
    	element_t e;
    	struct noeud_s *gauche;
    	struct noeud_s *droite;
    	struct noeud_s *parent;
    } t_noeud;
     
    typedef struct {
    	t_noeud *racine;
    } t_arbre;
     
    void arbre_init(t_arbre *a) {
    	a->racine=NULL;
    }
     
    t_noeud *nouveau_noeud(element_t a){
    	t_noeud *x;
    	x=malloc(sizeof(*x));
    	if (!x) {
    		perror("Echec malloc");
    		return NULL;
    	}
    	x->parent=NULL;
    	x->gauche=NULL;
    	x->droite=NULL;
    	x->e = a;
    	return x;
    }
     
    void inserer(t_noeud *n, t_arbre *a){
    	if (a->racine == NULL) {
    		a->racine=n;
    		return;
    	}
     
    	t_noeud *t=a->racine;
    	while (1) {
    		switch (comparer(n->e, 4)) {
    			case -1: 
    				if (t->gauche == NULL) {
    					t->gauche=n;
    					n->parent=t;
    					return;
    				}
    				t=t->gauche;
    				break;
    			case 1:
    				if (t->droite == NULL) {
    					t->droite=n;
    					n->parent=t;
    					return;
    				}
    				t=t->droite;
    				break;
    			case 0:
    				free(n);
    				return;
    				break;
    		}
    	}
    }
     
    void noeud_vider(t_noeud *n){
    	if (n == NULL) return;
    	noeud_vider(n->gauche);
    	noeud_vider(n->droite);
    	free(n);
    }
     
    void noeud_affich(t_noeud *n) {
    	if (n == NULL) return;
    	printf("%x (%f) - gauche=%x, droite=%x, parent=%x\n", n, n->e, n->gauche, n->droite, n->parent);
    	noeud_affich(n->gauche);
    	noeud_affich(n->droite);
    }
     
    int main() {
    	t_arbre arbre;
    	arbre_init(&arbre);
     
    	element_t tab[] = {0.7, 0.8, 6.7, 6, 7, 8.3, 9, 7.6};
     
    	for (size_t i = 0; i < 8; i++) {
    		inserer(nouveau_noeud(tab[i]), &arbre);
    	}
    	noeud_affich(arbre.racine);
    	noeud_vider(arbre.racine);
     
    	return EXIT_SUCCESS;
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 747
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 747
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Et ensuite je ne m'explique pas ta fonction "inserer" qui crée 2 noeuds.
    C'est qu'elle code un arbre de façon classique (ce qui ne devrait pas être trop difficile en théorie ), mais j'ai bien l'impression que c'est pour un arbre très spécial (voir un graphe) qui représente une matrice de distances - tout cela ne sert à rien

    Voir son précédent sujet : création d'un arbre à partir d'un fichier csv

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 801
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    C'est qu'elle code un arbre de façon classique (ce qui ne devrait pas être trop difficile en théorie )
    Ben... moi aussi je suis resté super classique. Une fonction qui crée le noeud, une autre qui l'insère à sa bonne place... Pas besoin de 2 noeuds quoi. Bon le cas "racine vide" à gérer évidemment et c'est bon. Juste que le cas où le noeud est déjà dans l'arbre m'a un peu cassé les noix car dans ce cas il est créé pour rien (je pense que t'auras remarqué que j'ai codé donc l'insertion un peu "à l'arrache " en rajoutant la verrue free(n) dans le cas où le noeud est déjà présent parce que j'avais la flemme de tout reprendre)...
    Citation Envoyé par foetus Voir le message
    mais j'ai bien l'impression que c'est pour un arbre très spécial (voir un graphe) qui représente une matrice de distances - tout cela ne sert à rien
    Ben surtout rien que ce "4"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Création d'arbre binaire en Java
    Par Mastyxx dans le forum Général Java
    Réponses: 7
    Dernier message: 30/11/2017, 16h33
  2. Afficher un arbre binaire avec sa structure
    Par PhoneKilleR dans le forum C
    Réponses: 7
    Dernier message: 23/04/2008, 23h24
  3. arbre binaire & création de noeud
    Par jayfaze dans le forum C
    Réponses: 4
    Dernier message: 18/10/2007, 15h13
  4. [débutant Java] création d'un arbre binaire
    Par barouz dans le forum Langage
    Réponses: 2
    Dernier message: 16/04/2006, 04h25
  5. Arbre binaire
    Par Heaven dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 02/02/2004, 19h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo