Forked from
algorithmique / cours
253 commits behind the upstream repository.
-
orestis.malaspin authoredorestis.malaspin authored
cours_22.md 9.69 KiB
title: "B-arbres"
date: "2023-05-19"
Rappel: Les B-arbres
Pourquoi utiliser un B-arbre?
. . .
À quoi ressemble un B-arbre?
. . .
n
Qu'est-ce qu'un B-arbre d'ordre- Chaque page d'un arbre contient au plus 2\cdot n clés;
- Chaque page (excepté la racine) contient au moins n clés;
- Chaque page qui contient m clés contient soit:
- 0 descendants;
- m+1 descendants.
- Toutes les pages terminales apparaissent au même niveau.
Rappel: Les B-arbres
Quelques propriétés
- Dans chaque nœud les clés sont triées.
- Chaque page contient au plus n nœuds;
- Chaque nœud avec m clés a m+1 descendants;
- Toutes les feuilles apparaissent au même niveau.
Les B-arbres
\footnotesize
Structure de données
- Chaque page a une contrainte de remplissage, par rapport à l'ordre de l'arbre;
- Un nœud (page) est composé d'un tableau de clés/pointeurs vers les enfants;
P_0 | K_1 | P_1 | K_2 | .. | P_i | K_{i+1} | .. | P_{m-1} | K_m | P_m
-
P_0
, ...,P_m
pointeurs vers enfants; -
K_1
, ...,K_m
les clés. - Il y a
m+1
pointeurs maism
clés. - Comment faire pour gérer l'insertion?
Les B-arbres
Faire un dessin de la structure de données (3min matrix)?
. . .
- On veut un tableau de
P_i, K_i => struct
; -
K_0
va être en "trop"; - Pour simplifier l'insertion dans une page, on ajoute un élément de plus.
Les B-arbres
4
?
L'insertion cas nœud pas plein, insertion
. . .
Solution
Les B-arbres
N
L'insertion cas nœud pas plein, insertion - On décale les éléments plus grand que
N
; - On insère
N
dans la place "vide"; - Si la page n'est pas pleine, on a terminé.
Les B-arbres
2
?
L'insertion cas nœud plein, insertion
. . .
Solution
Les B-arbres
3
?
L'insertion cas nœud plein, promotion
. . .
Solution
Les B-arbres
N
L'insertion cas nœud plein, insertion - On décale les éléments plus grand que
N
; - On insère
N
dans la place "vide"; - Si la page est pleine:
- On trouve la valeur médiane
M
de la page (quel indice?); - On crée une nouvelle page de droite;
- On copie les valeur à droite de
M
dans la nouvelle page; - On promeut
M
dans la page du dessus; - On connecte le pointeur de gauche de
M
et de droite deM
avec l'ancienne et la nouvelle page respectivement.
- On trouve la valeur médiane
Les B-arbres
Pseudo-code structure de données (3min, matrix)?
. . .
struct page
entier ordre, nb
element tab[2*ordre + 2]
struct element
entier clé
page pg
Les B-arbres
\footnotesize
Les fonctions utilitaires (5min matrix)
booléen est_feuille(page) // la page est elle une feuille?
entier position(page, valeur) // à quelle indice on insère?
booléen est_dans_page(page, valeur) // la valeur est dans la page
. . .
booléen est_feuille(page)
retourne (page.tab[0].pg == vide)
entier position(page, valeur)
i = 0
tant que i < page.nb && val >= page.tab[i+1].clef
i += 1
retourne i
booléen est_dans_page(page, valeur)
i = position(page, valeur)
retourne (page.nb > 0 && page.tab[i].val == valeur)
Les B-arbres
\footnotesize
Les fonctions utilitaires (5min matrix)
page nouvelle_page(ordre) // créer une page
rien liberer_memoire(page) // libérer tout un arbre!
. . .
page nouvelle_page(ordre)
page = allouer(page)
page.ordre = ordre
page.nb = 0
page.tab = allouer(2*ordre+2)
retourner page
rien liberer_memoire(page)
si est_feuille(page)
liberer(page.tab)
liberer(page)
sinon
pour fille dans page.tab
liberer_memoire(fille)
liberer(page.tab)
liberer(page)
Les B-arbres
Les fonctions (5min matrix)
page recherche(page, valeur) // retourner la page contenant
// la valeur ou vide
. . .
page recherche(page, valeur)
si est_dans_page(page, valeur)
retourne page
sinon si est_feuille(page)
retourne vide
sinon
recherche(page.tab[position(page, valeur)], valeur)
Les B-arbres
Les fonctions
page inserer_valeur(page, valeur) // insérer une valeur
. . .
page inserer_valeur(page, valeur)
element = nouvel_element(valeur)
// on change élément pour savoir s'il faut le remonter
inserer_element(page, element)
si element.page != vide && page.nb > 2*page.ordre
// si on atteint le sommet!
page = ajouter_niveau(page, element)
retourne page
Les B-arbres
Les fonctions
rien inserer_element(page, element) // insérer un element
// et voir s'il remonte
. . .
rien inserer_element(page, element)
si est_feuille(page)
placer(page, element)
sinon
sous_page = page.tab[position(page, element)].page
inserer_element(sous_page, element)
// un element a été promu
si element.page != vide
placer(page, element)
Les B-arbres
Les fonctions (5min matrix)
rien placer(page, element) // inserer un élément
. . .
rien placer(page, element)
pos = position(page, element.clé)
pour i de 2*page.ordre à pos+1
page.tab[i+1] = page.tab[i]
page.tab[pos+1] = element
page.nb += 1
si page.nb > 2*page.ordre
scinder(page, element)
Les B-arbres
Les fonctions (5min matrix)
rien scinder(page, element) // casser une page et remonter
. . .
rien scinder(page, element)
new_page = new_page(page.ordre)
new_page.nb = page.ordre
pour i de 0 à ordre inclu
new_page.tab[i] = page.tab[i+ordre+1]
element.clé = page.tab[ordre+1].clé
element.page = new_page
Les B-arbres
Les fonctions (5min matrix)
page ajouter_niveau(page, element) // si on remonte à la
// racine, on doit créer
// une nouvelle racine
. . .
page ajouter_niveau(page, element)
tmp = nouvelle_page(page.ordre)
tmp.tab[0].page = page
tmp.tab[1].clé = element.clé
tmp.tab[1].page = element.page
retourne tmp
Les B-arbres: suppression
Cas simplissime
. . .
Les B-arbres: suppression
\footnotesize
Cas simple
. . .
- On retire 27, mais....
- Chaque page doit avoir au moins 2 éléments.
- On doit déplacer des éléments dans une autre feuille! Mais comment?
. . .
Les B-arbres: suppression
Cas moins simple
. . .
- Un élément à droite, comment on fait?
- Remonter
7
, serait ok si racine, mais... c'est pas forcément. - On redistribue les feuilles.
- Remonter
. . .
Les B-arbres: suppression
\footnotesize
Cas ultra moins simple
. . .
-
7
seul:- Fusionner les feuilles et redistribuer, comment?
. . .