Arbre qui peut contenir la meme valeur

Résolu
micgamers Messages postés 4 Date d'inscription   Statut Membre Dernière intervention   -  
micgamers Messages postés 4 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,
Je travaille sur une application qui nécessite un arbre n-aire contenant plusieurs fois les memes valeurs.
Existe-t-il une classe en c++ qui permet de créer un arbre de ce type?
Du code aussi serait interessant.
merci beaucoup pour l'aide apportée.

6 réponses

mamiemando Messages postés 33777 Date d'inscription   Statut Modérateur Dernière intervention   7 884
 
Ok j'ai compris. Voici le code que je te propose sachant qu'il faut faire un destructeur propre pour node_t (en gros libérer les noeuds fils avant de se libérer, ce qui induit un appel récursif que je te laisse le plaisir d'écrire).
#include <map>
#include <vector>
#include <iostream>

// Un noeud de l'arbre
class node_t{
    protected:
    unsigned id; // l'id de ce noeud
    std::map<unsigned,struct node_t *> neigh; // les noeuds fils

    public:
    // Le constructeur par défaut
    node_t(){}

    // Le constructeur
    node_t(unsigned id0):id(id0){}

    // Accesseur
    inline unsigned get_id() const{
        return id;
    }

    // Ajouter un noeud fils si besoin
    struct node_t * add_neigh(unsigned id0){
        std::map<unsigned,struct node_t *>::iterator
            fit = neigh.find(id0);
        // Ce noeud fils existe déjà, on retourne son adresse
        if (fit != neigh.end()){
            return fit->second;
        }
        // Ce noeud fils n'existe pas
        node_t *new_node = new node_t(id0);
        neigh[id0] = new_node;
        return new_node;
    }

    protected:
    void show_impl(
        const std::vector<unsigned> & prefix // le morceau d'arbre actuellement parcouru
    ) const{
        if(neigh.empty()){ // on a atteint une feuille
            for(std::size_t i=0;i<prefix.size();++i) std::cout << prefix[i] << ' ';
            std::cout << std::endl;
        }else{ // il y a des noeuds fils
            std::map<unsigned,struct node_t *>::const_iterator
                mit (neigh.begin()),
                mend(neigh.end());
            // pour chaque fils
            for(;mit!=mend;++mit){
                const unsigned & id_next = mit->first;
                const node_t & node_next = *(mit->second);
                // on rajoute au prefixe courant l'id du noeud fils
                std::vector<unsigned> prefix_next = prefix;
                prefix_next.push_back(id_next);
                node_next.show_impl(prefix_next);
            }
        }
    }

    public:
    // Afficher ce noeud et ses noeud fils
    void show() const{
        show_impl(std::vector<unsigned>());
    }
};

// La classe d'arbre
class tree_t{
    protected:
    struct node_t *root; // le noeud racine

    // Fonction appelée récursivement pour insérer le chemin dans l'arbre
    // path = p1,p2,...
    // on est rendu à la position i (node_cur = pi)
    // on est en train d'inserer p(i+1) (node_next) si nécessaire
    void add_path_impl(
        const std::vector<unsigned> & path,
        struct node_t *node_cur,
        std::size_t i
    ){
        if(i==path.size()) return;
        struct node_t *node_next = node_cur->add_neigh(path[i]);
        add_path_impl(path,node_next,i+1);
    }

    public:

    // Le constructeur
    tree_t(){
        root = new node_t();
    }

    // Le destructeur
    ~tree_t(){
        delete root;
    }

    // Ajouter un chemin
    inline void add_path(const std::vector<unsigned> & path){
        add_path_impl(path,root,0);
    }

    // Afficher l'arbre
    inline void show() const{
        root->show();
    }
};

int main(){
    std::vector<unsigned> path1(4),path2(4),path3(3);
    path1[0] = 2; path1[1] = 4; path1[2] = 5; path1[3] = 4;
    path2[0] = 2; path2[1] = 4; path2[2] = 3; path2[3] = 7;
    path3[0] = 1; path3[1] = 2; path3[2] = 3;
    tree_t tree;
    tree.add_path(path1);
    tree.add_path(path2);
    tree.add_path(path3);
    std::cout << "tree built" << std::endl;
    tree.show();
    return 0;
}

Ce qui donne à la compilation et à l'exécution
(mando@polgara) (~) $ g++ -W -Wall -g plop.cpp
(mando@polgara) (~) $ ./a.out
tree built
1 2 3
2 4 3 7
2 4 5 4

Bonne chance
1
mamiemando Messages postés 33777 Date d'inscription   Statut Modérateur Dernière intervention   7 884
 
Si l'objectif c'est de stocker une collection d'objets ordonnés avec éventuellement des objets en plusieurs exemplaires tout en ayant un accès en O(log(n)), le mieux c'est d'utiliser directement un std::multiset.
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583

Exemple :
#include <iostream>
#include <set>

template <typename T>
bool cherche(const std::multiset<T> & m,const T & t){
    return (m.find(t) != m.end());
}

int main(){
    std::multiset<int> m;
    m.insert(2);
    m.insert(3);
    m.insert(1);
    m.insert(2);
    m.insert(4);
    m.insert(2);
    m.insert(3);

    {
        std::multiset<int>::const_iterator
            mit (m.begin()),
            mend(m.end());
        for(;mit!=mend;++mit) std::cout << *mit << ' ';
        std::cout << std::endl;
    }

    cherche(m,3) ?
        std::cout << "3 est dans m" << std::endl :
        std::cout << "3 n'est pas dans m" << std::endl;
    cherche(m,7) ?
        std::cout << "7 est dans m" << std::endl :
        std::cout << "7 n'est pas dans m" << std::endl;
    return 0;
}

En interne la STL utilise une structure d'arbre pour ranger ces éléments.
Si ce n'est pas ce que tu recherches, donne nous un exemple d'arbre que tu cherches à construire.

Bonne chance
0
micgamers Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
 
ok mais moi il me faut un arbre qui ne range pas les éléments car c'est un arbre qui contient des chemins. Donc les elements ne doivent pas etre rangées.

J'ai des traces qui sont comme ca :
1 2 56 12 78 2...
2 5 89 6 3 ...
1 2 56 11 ...

je dois obtenir quelque chose comme ça :
------------------ ø
-----------------/-----\
---------------1--------52
-------------/---\ ----/ ---\
------------5 ----1--- 1 -----6
-----------/-\---------\ ---/---\
----------52 --2-------- 5 -1-----52

Désolé pour les "-" un peu partout, c'est juste que l'editeur de texte ne prend pas en compte les grand espaces...


Voila à quoi ça doit ressemler... est ce que tu as une idée sur une classe qui pourrait remplir cette condition?
0
micgamers Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
 
Ok ça m'a l'air trés bien tout ça...
Je ne peux pas mettre en application pour le moment mais je pense que lundi ou mardi je te dirai si tout va comme je le souhaite.
En tout cas, merci beaucoup du temps que tu as passé pour répondre... c'est trés sympa...
à la semaine prochaine donc pour la réponse...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33777 Date d'inscription   Statut Modérateur Dernière intervention   7 884
 
Pas de soucis bon courage.
0
micgamers Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
 
Salut et un grand merci, c'est exactement ce qu'il me fallait...
La solution que tu as proposée est complète car je n'ai pas besoin de destructeur.
merci encore.
bye
0