Ici, nous allons voir les différentes techniques et opérations
chirurgicales liées à la représentation intervallaire : modifier le statut d'un élément (transformer un noeud en une feuille, et vice-versa), ajouter des feuilles à un noeud, compter le nombre d'éléments dans un noeud, pouvoir mettre à jour les indices aux bornes en fonction du nombre d'éléments (selon que ce sera une feuille ou un noeud), le déplacement de noeuds...
Cette partie du tuto agira donc en tant que plusieurs séries de "minis-TP", qui demandent par moments de la réflexion, et par moments des astuces... que je développerai ici.
Stats sur les différents noeuds
Dans cette sous-partie, nous allons voir comment compter le nombre d'éléments d'un noeud, le nombre de feuilles d'un noeud, le nombre de noeuds dans un même noeud, ... bref, on va compter.
Compter le nombre d'éléments d'un noeud
Pour compter le nombre d'éléments d'un noeud, ça va être relativement (très) simple, et (très) vite expédié. Vous vous souvenez, à la fin de la première partie de ce tuto, on a vu comment récupérer tous les parents (et leur caractéristiques) d'une feuille / d'un noeud, en incluant ou non l'élément, non ? Eh bien ici, ça va plus ou moins être le même topo.
Ha ! Laisse-moi deviner : au lieu d'inclure l'élément dans la sélection, on va déjà devoir utiliser les signes strictement supérieur / inférieur, non ?
Bingo ! De plus, vous aurez besoin, comme je l'ai dit,
non pas de sélectionner
les parents de l'élément,
mais ses enfants ! Donc, au lieu de rechercher tous les éléments qui ont une borne gauche inférieure à celle de l'élément recherché, et une borne droite supérieure à celle de l'élément, on va faire l'inverse !
Je vous file la solution dans quelques minutes, le temps pour vous de chercher (
et moi d'aller piquer un petit somme
). Ah, j'oubliais pour quel forum on va faire cette opération : cette fois-ci, on va chercher le nombre d'enfants pour le forum ayant l'ID numéro... 3 !
Petit indice : utilisez la fonction d'agrégat
COUNT(*) (pour les fonctions d'agrégat, voyez
le tutorial de Shepard sur le sujet).
...
...
Hmm ? Vous avez (
déjà) fini ? Voici donc la correction

.
Secret (cliquez pour afficher)
Code : SQL | SELECT COUNT(*)
FROM tuto_ri
WHERE forum_gauche > 3
AND forum_droite < 24;
|
Vous avez vu, ce n'était pas
si sorcier, il suffisait donc juste d'inverser les signes pour les deux bornes pour obtenir les enfants et non pas les parents du noeud, et d'utiliser, comme je vous l'ai dit, la fonction d'agrégat
COUNT(*).
On trouve donc 10 éléments fils au noeud '1.1.1'
Dans le sens inverse, on retrouve 2 éléments parents au noeud '1.1.1'
Compter le nombre de feuilles / de noeuds d'un noeud
Mais... Mais... N'est-ce pas la même chose que ce qu'on a fait à l'instant même ?
Pas tout à fait. Ici, on ne cherchera pas à compter tous les
enfants (ou les
parents) d'un noeud, mais
seulement les feuilles (ou les noeuds) enfants (ou les parents) d'un noeud. Donc, on va à peu près procéder de la même manière qu'auparavant, mais, tâchez juste de vous rappeler d'un des points à retenir de la représentation intervallaire. Vous y êtes ? Non ? Bon bah cherchez le nombre de noeuds enfants pour le même forum que le précédent

(
et ça va me permettre d'aller chercher un café pour finir de me réveiller
).
...
...
...
...
Que vous ayez fini ou non, voici la correction !
Secret (cliquez pour afficher)
Code : SQL | SELECT COUNT(*)
FROM tuto_ri
WHERE forum_gauche > 3
AND forum_droite < 24
AND (forum_droite - forum_gauche) = 1;
|
On trouve 7 feuilles filles pour le "Forum 1.1.1"
Ce TP était également plutôt facile ; il suffisait de se souvenir que pour
toutes les feuilles d'un arbre, la différence entre les deux bornes est
toujours égale à 1. De même, pour compter le nombre de noeuds fils, vous pouvez, je pense, aisément le deviner : il faut chercher non pas les fils ayant une différence entre leurs bornes égale à 1, mais supérieure à 1.
On trouve 3 noeuds fils pour le noeud "1.1.1"
On trouve 0 feuilles parentes pour le noeud "1.1.1"
On trouve 2 noeuds parents pour le noeud "1.1.1"
Mettre à jour un élément
Ici, on va voir comment mettre à jour un élément : mettre ses bornes à jour (ajout / suppression d'éléments), mise à jour qui peut entraîner la transformation d'une feuille en un noeud (et vice-versa

)... Bref, on va s'amuser à mettre à jour notre arbre.
Ajout / suppression d'éléments (transformation d'une feuille en un noeud "simple", d'un noeud "simple" en une feuille)
Déjà, vous devez savoir comment insérer / supprimer des lignes d'une base de données, à l'aide des requêtes
INSERT et
DELETE.... Vous y êtes ? On va insérer une nouvelle ligne par la droite à la feuille de niveau 4, 1.[...].3 (ID N°13). Pour cela, puisque nous connaissons déjà la borne gauche, la borne droite, et le niveau de la feuille, on évite une requête. Enfin, c'est à vous de voir si vous voulez (ou non) ajouter une requête
SELECT, ça dépend des cas.
De plus, on aura également besoin de faire 2
updates : changer les bornes gauches et droites de tous les éléments à partir desquels on souhaite insérer la nouvelle feuille. Donc, à chacune des bornes, on va incrémenter tout d'abord la borne droite de 2, puis la borne gauche de... 2 également, et le tout en 2 requêtes. Pourquoi deux ? Pour ne pas nous embêter à pondre un truc trop complexe, et pour une raison que je préciserai dans le corrigé, plus bas. Après tout, pourquoi faire complexe quand on peut faire simple ?
Et enfin, on insère la nouvelle feuille... par la droite. Pourquoi par la droite ? Parce que c'est plus pratique...

Mais après, libre à vous de suivre le conseil que je vous donne (qui est également celui de M Brouard).
Ici, on cherche donc à insérer notre nouvelle feuille
par la droite : je vous laisse un peu de temps (pour percuter) et essayer de pondre les requêtes.
Euh... Mais attends, je comprends pas, pourquoi appelles-tu ceci un noeud "simple"

?
Ah, c'est vrai, je n'ai pas détaillé. J'appelle ici noeud "simple" le fait que ce noeud n'ait qu'une feuille, et le fait que l'on insère que des feuilles.... et non pas des noeuds. Je détaillerai dans le prochain mini-TP comment procéder dans ce cas (pour retirer un noeud d'un arbre aussi

). Bref, allez-y, la correction arrive dans quelques instants

.
...
...
...
Voici la correction tant désirée.
Secret (cliquez pour afficher)
Code : SQL | UPDATE tuto_ri
SET forum_droite = forum_droite + 2
WHERE forum_droite >= 22;
UPDATE tuto_ri
SET forum_gauche = forum_gauche + 2
WHERE forum_gauche >= 22;
INSERT INTO tuto_ri (forum_level, forum_gauche, forum_droite, forum_name)
VALUES (5, 22, 23, '1.1.1.1.3.1');
|
Insertion d'une feuille dans un noeud / une feuille
Vous ayant tout expliqué avant, c'était juste une application de ce que j'ai dit plus haut.
Lorsqu'on sélectionne les données, on trouve la feuille insérée à la bonne place (ici, je n'ai sélectionné que les colonnes
forum_gauche,
forum_droite, et
forum_name, pour éviter d'avoir une largeur trop grande pour mon screen) :
OK, tout est correct !
Vous pouvez ainsi transformer une "simple" feuille en un noeud... "simple".
Je pense que vous devinerez comment supprimer une feuille :
Code : SQL | DELETE
FROM tuto_ri
WHERE forum_gauche = 22;
UPDATE tuto_ri
SET forum_gauche = forum_gauche - 2
WHERE forum_gauche >= 22;
UPDATE tuto_ri
SET forum_droite = forum_droite - 2
WHERE forum_droite >= 22;
|
Le topo est à peu près le même que pour l'insertion, sauf que cette fois-ci, on procède d'abord à la suppression, puis à la mise à jour de la borne gauche, et enfin à la mise à jour de la borne droite ; j'expliquerai pourquoi, lors de l'insertion, on commence toujours par la mise à jour de la borne droite, puis on s'occupe de la borne gauche, puis de l'insertion, et dans le sens inverse lors de la suppression (enfin, on change l'insertion par la suppression, je pense que pour ça, vous avez déjà percuté

), plus bas pour résumer ce TP.
Suppression d'une feuille dans un noeud / retransformation d'un noeud "simple" en une feuille
On retourne à l'état initial
Alors ? Pourquoi recommandes-tu d'exécuter ces actions dans cet ordre précis ?
C'est juste pour ne pas avoir d'erreurs trop bêtes, si vous avez mis des contraintes d'unicité sur vos deux bornes. Ainsi, lors de l'insertion, on décale d'abord toutes les bornes à partir desquelles on veut insérer notre feuille, pour pouvoir ensuite décaler les bornes gauches des feuilles suivantes sans que la borne gauche ne soit jamais égale à une borne droite, et vice-versa (phew). Ensuite seulement, on insère la feuille à la borne désirée. Pour la suppression, c'est à peu près le même topo, mais dans le sens inverse.
Pour la suppression, vous n'êtes pas obligés de tout re-décaler, mais suivez mon conseil, et faites-le, histoire d'avoir un arbre plus propre et ne pas avoir "trop" de trous et pas mal d'emmerdes au fur et à mesure des différentes opérations.
Maintenant, si vous êtes toujours là, on va aborder la même chose... Mais avec des noeuds, c'est-à-dire l'insertion et la suppression d'un noeud dans un arbre !
Insertion / suppression d'un sous-arbre (noeud) dans un arbre
Je ne pense pas avoir besoin de trop détailler. Vous avez juste besoin de connaître les bornes de l'arbre à insérer, le nombre d'éléments qu'il contient, et ça devrait faire l'affaire, si on emploie la même méthode que tout à l'heure.
Voici l'arbre que l'on va chercher à insérer :
On va donc rattacher cet arbre à la feuille "2", c'est-à-dire celle étant comprise entre les bornes... 39 et 40. En ayant cet arbre, et sachant qu'il y a
9 éléments, la différence entre les deux bornes de la catégorie 2 va être égale à (je sors ma calculette

) : 2 * 9 + 1, soit 19. La borne droite de notre nouveau "conteneur" sera donc de 58 (car, d'après ma calculette,
58 - 19 = ...
39 !) ; on aura aussi besoin d'incrémenter toutes les bornes droites du noeud à insérer du double du nombre d'éléments, soit... 9 * 2.. 18 !
Je vous laisse cogiter un peu (n'oubliez pas de décaler les bornes de l'arbre à insérer... Vous verrez que c'est plutôt facile

)...
...
...
Rendez vos copies, voilà la correction !
Secret (cliquez pour afficher)
Code : SQL 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | UPDATE tuto_ri
SET forum_droite = forum_droite + 18
WHERE forum_droite >= 39;
UPDATE tuto_ri
SET forum_gauche = forum_gauche + 18
WHERE forum_gauche > 39;
INSERT INTO tuto_ri (forum_level, forum_gauche, forum_droite, forum_name)
VALUES
(1, 40, 57, '2.1'),
(2, 41, 46, '2.1.1'),
(2, 47, 48, '2.1.2'),
(2, 49, 50, '2.1.3'),
(2, 51, 56, '2.1.4'),
(3, 42, 43, '2.1.1.1'),
(3, 44, 45, '2.1.1.2'),
(3, 52, 53, '2.1.4.1'),
(4, 54, 55, '2.1.4.2');
|
Insertion d'un arbre (noeud) dans un noeud : transformation d'une feuille en un noeud
Bon, c'est vrai, fallait faire des maths : ajouter 39 (borne gauche du nouveau parent, c'est-à-dire la catégorie 2) à toutes les bornes de ce noeud (et à ses éléments fils), pour le rendre "compatible" avec notre arbre récepteur. Ensuite, c'était une insertion des plus banales : il faut décaler les bornes de tous les éléments de notre arbre de.. petit calcul...
18 (à partir de la borne gauche
- non incluse - du nouveau parent), pour le rendre compatible avec notre arbre. Soit le double du nombre d'éléments à rajouter (9 éléments dans notre cas). Pour les niveaux, il "suffisait" juste de sélectionner les niveaux de l'arbre, et leur additionner le niveau du noeud auquel on veut fixer le nouvel arbre. Or, comme notre noeud "récepteur" a un niveau égal à 0... dans notre cas, ça n'a aucun effet (si ce n'est consommer des ressources).
Et voilà le travail
Voici la suppression (vous pouviez la deviner, quand même

) :
Code : SQL 1
2
3
4
5
6
7
8
9
10
11
12 | DELETE
FROM tuto_ri
WHERE forum_gauche > 39
AND forum_droite < 58;
UPDATE tuto_ri
SET forum_gauche = forum_gauche - 18
WHERE forum_gauche > 39;
UPDATE tuto_ri
SET forum_droite = forum_droite - 18
WHERE forum_droite >= 58;
|
C'était tout simplement un mélange entre l'application de la suppression d'une feuille et l'insertion d'un arbre. Comme pour la suppression d'une feuille, les mises à niveau des bornes de l'arbre dans lequel on a supprimé notre noeud ne sont pas obligatoires, mais restent un plus non négligeable pour avoir un arbre propre, et pour pouvoir éviter les trous trop gros dans l'arbre au fur et à mesure des opérations.
Dans notre cas, comme pour l'insertion, la mise à jour des bornes gauche de tous les éléments n'était pas nécessaire, car notre catégorie 2 se transforme en simple feuille, tout en étant la dernière de notre arbre.
Suppression d'un sous-arbre (noeud à plusieurs éléments fils) dans un noeud : transformation d'un noeud en une feuille
On retourne à notre configuration initiale