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

Algorithmes et structures de données Discussion :

Implémentation d'un B+Tree pour le stockage d'une liste


Sujet :

Algorithmes et structures de données

  1. #1
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut Implémentation d'un B+Tree pour le stockage d'une liste


    Je vous expose la situation : il semblerai que les B+Tree soient les plus utilisés quand il s'agit de représenter une hiérarchie dans un système de fichier afin de stocker la liste des éléments enfants d'un dossier donné. En effet, avoir du O(log(n)) pour presque toues les opérations semble plutôt bien (moi je suis pour l'instant en O(n) avec la méthode la plus basique qui soit pour enregistrer ma liste ... ).

    Je voudrais donc implémenter mon propre B+Tree pour mon "système de fichier" (plus une base de donnée) afin d'améliorer les temps d'accès et de modifications des nodes. Cependant en cherchant sur le net soit j'ai trouvé des exemples trop spécialisés pour être utilisés (j'y comprends rien ) soit il manquait certaines opérations (dont la suppression d'une node, j'en ai besoin). Existe-t-il des descriptions complètes de l'algo sous une forme "simple" (pseudocode) sur le net ?

    Petite précision, je fonctionne avec des blocks de 64 octets, en comptant que chaque "pointeur" fait 8 octets je peut donc en mettre 8 par node. Donc à priori 7 de données et le 8ième qui pointe vers la node suivante. Les nodes doivent cependant êtres comparées par le nom, qui peut être obtenu en le lisant à partir du pointeur de la node (mais qui se trouve dans un autre bloc, avec ~32760 caractères maxi). Par contre, la lecture d'un bloc n'est pas très rapide donc une économie de n vers log(n) pourrait être intéressante. Le B+Tree est-il adapté à mon problème ?

    Merci d'avance

  2. #2
    Expert confirmé
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Par défaut
    Existe-t-il des descriptions complètes de l'algo sous une forme "simple" (pseudocode) sur le net ?
    SUr le net je ne sais pas trop, tu peux trouver des infos dans le Cormen (introduction à l'algorithmique - chapitre 18 pour la deuxième édition)

    Tu pourras également trouver des infos dans le Handbook of Data structures and applications (Chapman - chapitre 15)

  3. #3
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Le truc c'est qu'il n'y a pas de libraires vendant ce genre de choses à coté de chez moi (je suis loin, même pas en France Métro) donc bon ... j'avais donc espéré qu'il existe des ressources (pdf, doc, html, etc...) montrant une implémentation simple du B+Tree (ou même, d'un B-Tree d'ordre 6 ou 7 si j'ai bien compris ce que ça veux dire) en pseudocode ou en pascal (facile à comprendre, avec le C/C++ les pointeurs commencent à noircir l'algo)... ça n'existe pas ?

  4. #4
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Sur :
    http://en.wikipedia.org/wiki/B%2B_tree
    et http://en.wikipedia.org/wiki/B-tree

    Il y a un max de lien en dans la partie Ressources. Tu n'as rien trouvé de bien ?


    Il y a des sources Java et C++ d'ailleurs.

  5. #5
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Ben en fait chacune des sources présentées proposent une implémentation spécialisée de l'algo et finalement l'idée même du principe est un peut masqué (d'ailleurs les exemples que j'ai trouvé en C# ne sont pas vraiment documentés). Pour le C++ ... je suis nase en C++.
    C'est pour celà que je voulais d'une source en "pseudocode" afin de n'avoir que l'algo devant moi car je ne sais pas trop comment je vais l'implémenter (j'ai finalement trouvé quelques problèmes dont des possibles collisions avec des clefs différents qui auraient le même id.) donc voilà, les details de chaque langage alourdissent l'algo ... Mais je pense que je vais essayer de me lancer dans un BTree perso mais beaucoup de détails sont encore bizarres pour moi :

    Pour éviter d'accéder à un bloc trop souvent, je peut enregistrer un hashcode fait à partir du nom de la clef -> problème des collisions
    Mes "pointeurs" dans la BdD font aussi 8 octets, donc pour les feuilles j'aurai 7 clefs et pour les nodes internes 4 séparés par 3 hashcode -> what ?
    Et aussi savoir où stocker les hashcode.
    En fait j'ai de plus en plus l'impression que je vais m'orienter vers un arbre binnaire, mais la perte question espace risque d'être grande vis à vis d'une simple liste des clefs ...

  6. #6
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    On va faire autrement. Quel type de données veux tu exactement enregistrer ?

    Et qu'elles sont les opérations que tu souhaites ?

  7. #7
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Bon ben j'explique en détail mon architecture :
    Je travaille avec des blocks de 64 octets, et des pointeurs (identifiants des blocks) codés sur 8 octets (ulong).
    Les nodes sont des pointeurs vers le début d'un bloc et le reste est une liste chainée jusqu'au dernier bloc qui pointe vers 0 comme bloc suivant (bloc 0 invalide, car c'est une des maps qui enregistre les blocs alloués ou vides, donc fin du flux).
    Chaque node à un nom qui est lui aussi dans une bloc chainé pointé par un ulong à l'offset 16 de la node et codé en UTF8. Il y a aussi un pointeur vers la liste des nodes enfants qui se présente comme un bloc chainé commençant par un uint (nombre d'éléments) et ensuite les enfants sous forme de ulong ce qui fait qu'au bout du 7e ulong (dans le premier bloc) je passe au bloc suivant. Pour l'instant, pour obtenir une node je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    De i = 0 à nombre - 1 :
     Lecture du pointeur (passage au bloc suivant si nécéssaire)
     Obtention du bloc contenant le nom
     Lecture du nom
     Si le nom est celui cherché, on renvoi la node
     Sinon, étape suivante
    Fin
    Donc ça me fait un O(n) et le passage au bloc suivant peut être long car il faut parfois charger 32 kb depuis le fichier et en .NET c'est lent l'accès au fichier (il y a un cache donc de 32 x 16 kb mais vu que les blocs ne se suivent pas forcément c'est très long).

    Ce que je veux donc faire c'est mettre en place un algo qui me permette de diminuer le nombre de blocs à visiter avant de trouver la node cherchée. A la limite on peut supposer que le nom d'une node ne changera pas (cette opération étant rare, je peut me suffire à supprimer la node de la liste, changer son nom, et l'ajouter de nouveau). Pour l'instant au pire pour rajouter/supprimer une node je dois visiter n blocs et en visiter log(n) serait vraiment un énorme gain (vu que n peut être supérieur à 1000 et l'opération répétée un nombre important de fois).
    Je cherche donc des méthodes qui prennent en compte la nature des accès aux données qui se fait par bloc et qui évite aussi de devoir allouer 10 blocs pour contenir 1 seul élément et qui permette donc d'amortir d'une manière logarithmique les temps de recherche/ajout/suppression des nodes de la liste.
    Je pourrai aussi essayer de générer un hashcode pour le nom des nodes qui évite de devoir lire une chaine à chaque fois pour comparer, avec la méthode de supprimer la node pour la renommer.

    So ?
    (c'est affreux )

  8. #8
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    L'ordre est important de tes noeuds dans le fichier où la seule chose qui importe c'est le fait qu'il y ait un ensemble de (clef = nom, objet) ?



    en .NET c'est lent l'accès au fichier
    J'y connais rien en .NET (pourquoi connaître d'ailleurs ), mais tu travailles bien avec des flux bufferisés en lecture ? Tu peux avancer les curseurs dans les fichiers sans les lire ? (fonctionnalité utile surtout que dans le cas d'un BTree ou d'une sorte de TreeMap)

  9. #9
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Citation Envoyé par millie Voir le message
    L'ordre est important de tes noeuds dans le fichier où la seule chose qui importe c'est le fait qu'il y ait un ensemble de (clef = nom, objet) ?
    L'ordre est délibérément insignifiant
    Je voudrais juste pouvoir accéder à mes nodes par leur nom en un temps en O(log(n)) ou similaire. Simplement que si un ordre est nécéssaire pour l'algo, je pourrai les ranger par leur nom (qui n'est pas sensible à la casse).

    Citation Envoyé par millie Voir le message
    J'y connais rien en .NET (pourquoi connaître d'ailleurs ), mais tu travailles bien avec des flux bufferisés en lecture ? Tu peux avancer les curseurs dans les fichiers sans les lire ? (fonctionnalité utile surtout que dans le cas d'un BTree ou d'une sorte de TreeMap)
    J'ai fait mes propres classes pour garder le maximum d'infos du flux en mémoire. En fait je travail avec des "pages" de 32kb que je charge en mémoire et que je décharge seulement si le chargement d'une page est demandé et que la mémoire tampon est pleine (au bout de 16 pages chargées elle est pleine) et dans ce cas j'écris les données dans le flux si elles ont été changées. Le seul moment où j'accède au flux (et donc qu'il y a un gros ralentissement) c'est au chargement/déchargement de la page. Tout le reste se fait en mémoire. Donc le curseur je peut le mettre ou je veux. Avec un peut de chance la page sera déjà en mémoire lors de la prochaine lecture. Sans chance, il faudra lire la page.

  10. #10
    Membre très actif
    Avatar de teddyalbina
    Homme Profil pro
    Développeur .Net,C++
    Inscrit en
    Janvier 2008
    Messages
    466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .Net,C++

    Informations forums :
    Inscription : Janvier 2008
    Messages : 466
    Par défaut
    Pourquoi n'utiliserais tu pas Berkeleydb ? qui implémente le B+Tree sans compter que la vitesse de cette lib est difficilement égalable.

    http://www.oracle.com/technology/pro...-db/index.html

  11. #11
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Citation Envoyé par teddyalbina Voir le message
    Pourquoi n'utiliserais tu pas Berkeleydb ? qui implémente le B+Tree sans compter que la vitesse de cette lib est difficilement égalable.
    Parce que (pas envie de faire un pavé ), on va dire que j'aime le sport

    Bon, j'ai à peut près réussit (enfin, en théorie) a reformuler mon problème d'un B+Tree/B-Tree/BTree incompréhensible à un Binary Tree déjà plus simple (au moins là le code pour supprimer une clef n'est pas "left as an exercice" ... ).

    Maintenant on dirait que j'ai un autre problème : il semblerai que quand mon arbre est plein, l'algo d'énumération (Iterative In-Order Tree Traversing, vu que je ne veux surtout pas risquer les StackOverflow) fonctionne mais qu'il arrive dans un infinite loop quand il ne l'est pas entièrement ... c'est bien comme celà qu'il faut faire ?
    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
     
    List<ulong> result = new List<ulong>();
     
                int count = 0;
                ulong next = 0;
                ulong prev = 0;
                ulong parent = 0;
     
                ulong c_left = 0;
                ulong c_right = 0;
                while (count < maxcount && startNode != 0)
                {
                    /* on obtient la clef de gauche */
                    c_left = BinaryTree_Node_GetElement(startNode, BinaryTreeElement.LeftKey);
                    /* on obtient la clef de droite */
                    c_right = BinaryTree_Node_GetElement(startNode, BinaryTreeElement.RightKey);
                    /* on obtient la clef parente */
                    parent = BinaryTree_Node_GetElement(startNode, BinaryTreeElement.ParentKey);
     
                    if(prev == parent)
                    {
                        prev = startNode;
                        next = c_left;
                    }
     
                    if(next == 0 || prev == c_left)
                    {
                        result.Add(startNode);
                        count++;
                        prev = startNode;
                        next = c_right;
                    }
     
                    if(next == 0 || prev == c_right)
                    {
                        prev = startNode;
                        next = parent;
                    }
     
                    startNode = next;
                }
    startNode c'est le point de départ, en l'occurrence la racine, et je sais, c'est du C#, mais c'est l'algo qui m'intéresse pas le code en lui même.

    De l'aide ?

  12. #12
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Citation Envoyé par smyley Voir le message
    Maintenant on dirait que j'ai un autre problème : il semblerai que quand mon arbre est plein, l'algo d'énumération (Iterative In-Order Tree Traversing, vu que je ne veux surtout pas risquer les StackOverflow) fonctionne mais qu'il arrive dans un infinite loop quand il ne l'est pas entièrement ... c'est bien comme celà qu'il faut faire ?
    L'algo m'a l'air bon.

    Ton problème doit venir de la condition du while:
    Quand ton arbre n'est pas plein, il semblerait que les elements c_left/c_right ne soient pas à zéro.
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  13. #13
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Mais quelle est la condition que je devrais vérifier ? d'autant plus que appeller BinaryTree_Node_GetElement avec pour node 0 n'a pas de sens (=> crash) ...

  14. #14
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Citation Envoyé par smyley Voir le message
    Mais quelle est la condition que je devrais vérifier ? d'autant plus que appeller BinaryTree_Node_GetElement avec pour node 0 n'a pas de sens (=> crash) ...
    La condition du while est bonne.

    C'est dans les elements de ton arbre "non plein" qu'il doit y avoir un problème.
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  15. #15
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    J'ai fait une fonction CheckIntegrity pour vérifier et ... crash
    Chaque élément a un pointer vers left, right, et parent, mais en parcourant l'arbre en descendant au trouve que left n'a pas comme parent son véritable parant ...
    Il doit donc y avoir un problème dans la méthode qui supprimes les clefs. Je met le code ici (en espérant que ça vous inspire ).

    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
     
    public virtual bool BinaryTree_Node_Delete(ulong target, string nodeName)
            {
                ChainManager.Chain_CheckInvalidBlock(target);
     
                ulong primaryTarget = target;
     
                lock (nodeOperations)
                {
                    /* Déjà on cherche */
                    ulong node = BinaryTree_Node_Search(target, nodeName);
     
                    if (node == 0)
                        return false; /* Man ? she doesn't exists ! */
                    else
                    {
                        /* let's do */
                        /* déjà on obtient l'enfant droit et gauche */
                        ulong right = BinaryTree_Node_GetElement(node, BinaryTreeElement.RightKey);
                        ulong left = BinaryTree_Node_GetElement(node, BinaryTreeElement.LeftKey);
                        ulong parent = BinaryTree_Node_GetElement(node, BinaryTreeElement.ParentKey);
     
                        if (left == 0 && right == 0)
                        {
                            /* Aucun enfant, on supprime juste du parent */
                            if (parent != 0)
                            {
                                if (BinaryTree_Node_GetElement(parent, BinaryTreeElement.LeftKey) == node)
                                {
                                    /* On supprime la gauche */
                                    BinaryTree_Node_SetElement(parent, BinaryTreeElement.LeftKey, 0);
                                }
                                else
                                {
                                    /* Sinon la droite */
                                    BinaryTree_Node_SetElement(parent, BinaryTreeElement.RightKey, 0);
                                }
                            }
                            else
                            {
                                /* On vient de supprimer la racine et elle n'avais aucun enfant O_o ... plus de racine */
                                BinaryTree_Node_SetElement(target, BinaryTreeElement.ChildsRoot, 0);
                            }
                        }
                        else if (left == 0 || right == 0)
                        {
                            BinaryTree_Node_DeleteWithOneChild(target, node, right, left, parent);
                        }
                        else
                        {
                            /* Bon, on a deux enfants sur les bras */
     
                            /* On cherche d'abord le noeud le plus à gauche de l'abre droit */
                            ulong tempRes = right;
                            ulong temp = 0;
                            while ((temp = BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.LeftKey)) != 0)
                            {
                                tempRes = temp;
                            }
     
                            /* On le supprime de l'endroit où il était */
                            BinaryTree_Node_DeleteWithOneChild(target, tempRes,
                                BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.RightKey), 0,
                                BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.ParentKey));
     
                            /* On remplace la clef à supprimer par la valeur de ce dernier */
                            if (parent != 0)
                            {
                                if (BinaryTree_Node_GetElement(parent, BinaryTreeElement.LeftKey) == node)
                                {
                                    /* On supprime la gauche */
                                    BinaryTree_Node_SetElement(parent, BinaryTreeElement.LeftKey, tempRes);
                                }
                                else
                                {
                                    /* Sinon la droite */
                                    BinaryTree_Node_SetElement(parent, BinaryTreeElement.RightKey, tempRes);
                                }
     
                                BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.ParentKey, parent);
                            }
                            else
                            {
                                /* nouveau root : l'élément trouvé */
                                BinaryTree_Node_SetElement(target, BinaryTreeElement.ChildsRoot, tempRes);
                                BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.RootOwner, target);
                                BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.ParentKey, 0);
                            }
     
                            /* On modifie son left et right */
                            BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.LeftKey, left);
                            BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.RightKey, right);
                        }
     
     
                        BinaryTree_Node_SetChildCount(primaryTarget, BinaryTree_Node_GetChildCount(primaryTarget) - 1);
     
     
                        return true;
                    }
                }
            }
     
            protected virtual void BinaryTree_Node_DeleteWithOneChild(ulong target, ulong node, ulong right, ulong left, ulong parent)
            {
                /* La node n'a qu'un enfant, on la remplace simplement par celui ci dans le parent */
                if (parent != 0)
                {
                    if (BinaryTree_Node_GetElement(parent, BinaryTreeElement.LeftKey) == node)
                    {
                        /* On supprime la gauche */
                        BinaryTree_Node_SetElement(parent, BinaryTreeElement.LeftKey, right != 0 ? right : left);
                    }
                    else
                    {
                        /* Sinon la droite */
                        BinaryTree_Node_SetElement(parent, BinaryTreeElement.RightKey, right != 0 ? right : left);
                    }
     
                    BinaryTree_Node_SetElement(right != 0 ? right : left, BinaryTreeElement.ParentKey, parent);
                }
                else
                {
                    /* nouveau root : l'unique enfant */
                    BinaryTree_Node_SetElement(target, BinaryTreeElement.ChildsRoot, right != 0 ? right : left);
                    BinaryTree_Node_SetElement(right != 0 ? right : left, BinaryTreeElement.RootOwner, target);
                    BinaryTree_Node_SetElement(right != 0 ? right : left, BinaryTreeElement.ParentKey, 0);
                }
            }

    so ?

  16. #16
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Je résume les 3 cas à gerer en cas de suppression d'un noeud N:

    cas 1: le noeud N n'a pas d'enfants --> suppression de N

    cas 2: le noeud N a un enfant --> l'enfant remplace le noeud N

    cas 3:le noeud a deux d'enfants --> on cherche le noeud suivant (in order) S, on supprime S (cas 1 ou 2) et on remplace N par S

    Dans tous les cas, on n'oublie pas de mettre a jour les pointeurs parent/gauche/droite.

    On est d'accord ?
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  17. #17
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Bon ben j'avais oublié de mettre à jour les left et right pour le remplacement de la clef lors de la suppression d'une node avec 2 enfants. Maintenant le check passe sans problème avec ce code :
    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
     
    /* On cherche d'abord le noeud le plus à gauche de l'abre droit,
                 * donc le suivant. On est sur qu'il sera pas nul (au moins right non nul) */
                ulong tempRes = right;
                ulong temp = 0;
                while (true)
                {
                    temp = BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.LeftKey);
                    if (temp != 0)
                        tempRes = temp;
                    else
                        break;
                }
     
                /* On le supprime de l'endroit où il était
                 * elle a soit 0, soit 1 enfant.
                 * */
                BinaryTree_Node_Delete(target, tempRes);
                //BinaryTree_Node_DeleteWithOneChild(target, tempRes,
                //    BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.RightKey), 0,
                //    BinaryTree_Node_GetElement(tempRes, BinaryTreeElement.ParentKey));
     
                /* On remplace la clef à supprimer par la valeur de ce dernier */
                if (parent != 0)
                {
                    if (BinaryTree_Node_GetElement(parent, BinaryTreeElement.LeftKey) == node)
                    {
                        /* On remplace la gauche */
                        BinaryTree_Node_SetElement(parent, BinaryTreeElement.LeftKey, tempRes);
                    }
                    else
                    {
                        /* Sinon la droite */
                        BinaryTree_Node_SetElement(parent, BinaryTreeElement.RightKey, tempRes);
                    }
     
                    BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.ParentKey, parent);
                }
                else
                {
                    /* nouveau root : l'élément trouvé */
                    BinaryTree_Node_SetElement(target, BinaryTreeElement.ChildsRoot, tempRes);
                    BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.RootOwner, target);
                    BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.ParentKey, 0);
                }
     
                /* On modifie son left et right */
                BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.LeftKey, left);
     
                ulong newRight = tempRes != right ? right : 
                    BinaryTree_Node_GetElement(right, BinaryTreeElement.RightKey);
                BinaryTree_Node_SetElement(tempRes, BinaryTreeElement.RightKey, newRight  );
     
                BinaryTree_Node_SetElement(left, BinaryTreeElement.ParentKey, tempRes);
                if (newRight != 0)
                {
                    BinaryTree_Node_SetElement(newRight, BinaryTreeElement.ParentKey, tempRes);
                }

    Bon, c'est pas encore résolu, il faut que j'intègre le tout dans ma BdD mais je sens la fin approcher

  18. #18
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par smyley Voir le message
    Le truc c'est qu'il n'y a pas de libraires vendant ce genre de choses à coté de chez moi (je suis loin, même pas en France Métro) donc bon ... j'avais donc espéré qu'il existe des ressources (pdf, doc, html, etc...) montrant une implémentation simple du B+Tree (ou même, d'un B-Tree d'ordre 6 ou 7 si j'ai bien compris ce que ça veux dire) en pseudocode ou en pascal (facile à comprendre, avec le C/C++ les pointeurs commencent à noircir l'algo)... ça n'existe pas ?
    http://www.jcolibri.com/livres/livre...el_indexe.html

  19. #19
    Expert confirmé
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Par défaut
    Tient j'avais oublié ce message
    Bon ben entre temps j'ai réussit à faire mon petit BTree et j'ai investit sur un AVL Tree (dont je n'ai rien compris) qui permet de rendre tout ça plus amusant.
    Merci à tous ceux qui m'ont inspiré

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. cliquer sur un bouton pour tout selectionner dans une liste multiple
    Par PAYASS59 dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 23/07/2007, 15h33
  2. aide pour le tri d'une liste
    Par dany9 dans le forum C
    Réponses: 13
    Dernier message: 01/03/2007, 10h52
  3. [Avancés pour débutante]Stockage d'une table (tableau associatif)
    Par delma dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 17/11/2006, 12h16
  4. Réponses: 28
    Dernier message: 24/05/2006, 18h20
  5. [CSS] largeur fixe pour les elements d'une liste
    Par arnolpourri dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 24/05/2006, 13h25

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