Forked from
algorithmique / cours
231 commits behind the upstream repository.
-
Gabriel Marino J authoredGabriel Marino J authored
- Les arbres quaternaires
- Définition
- Les arbres quaternaires
- Cas d'utilisation
- Cas d'utilisation: images
- Cas d'utilisation: simulation
- Exemple de compression
- Comment représenter l'image
- Sous la forme d'un arbre quaternaire?
- Structure de données
- Pseudo-code?
- En C?
- Une fonctionnalité simple
- La fonction est_feuille(noeud)
- Structure de données
- En C?
- Fonction is_leaf(node *tree)?
- Problème à résoudre
- Création de l'arbre
- Comment créer un arbre de profondeur prof (3min)?
- En C (3 min, matrix)?
- Le nombre de nœuds?
- Comment implémenter la fonction (pseudo-code, 5min, matrix)?
- Le nombre de nœuds?
- Comment implémenter la fonction en C (3min, matrix)?
- La profondeur en C?
- Implémentation (5min, matrix)
- Fonctions utiles (1/4)
- Comment remplir un arbre depuis une matrice?
- Quel arbre cela représente?
- Fonctions utiles (2/4)
- Soit ligne=2, colonne=3
- Trouver un algorithme
- Fonctions utiles (3/4)
- Soit ligne=2, colonne=3
- Trouver un algorithme (prendre plusieurs exemples, 15min, matrix)
- Fonctions utiles (4/4)
- Pseudo-code
- Écrire le code C correspondant (5min, matrix)
- Remplir l'arbre
- A partir d'une matrice (pseudo-code, 5min, matrix)?
- A partir d'une matrice (C, 5min, matrix)?
- Remplir la matrice
- A partir de l'arbre (pseudo-code, 3min, matrix)?
- A partir de l'arbre (C, 3min, matrix)?
cours_19.md 7.73 KiB
title: "Arbres quaternaires"
date: "2023-04-28"
Les arbres quaternaires
Définition
Arbre dont chaque nœud a 4 enfants ou aucun.
Les arbres quaternaires
Cas d'utilisation
Typiquement utilisés pour représenter des données bidimensionnelles.
Son équivalent tri-dimensionnel est l'octree (chaque nœud a 8 enfants ou aucun).
Cas d'utilisation: images
- Stockage: compression.
- Transformations: symétries, rotations, etc.
Cas d'utilisation: simulation
- Indexation spatiale.
- Détection de collisions.
- Simulation de galaxies, Barnes-Hut.
Exemple de compression
::: columns
:::: {.column width=30%}
Comment représenter l'image
::::
:::: {.column width=70%}
Sous la forme d'un arbre quaternaire?
. . .
Économie?
. . .
Image 64 pixels, arbre 25 nœuds.
::::
:::
Structure de données
::: columns
:::: {.column width=50%}
Pseudo-code?
. . .
struct node
info
node sup_gauche, sup_droit,
inf_gauche, inf_droit
::::
:::: {.column width=50%}
En C?
. . .
struct _node {
int info;
struct _node *sup_left;
struct _node *sup_right;
struct _node *inf_left;
struct _node *inf_right;
};
- Pourquoi le
*
est important?
. . .
- Type récursif => taille inconnue à la compilation.
::::
:::
Une fonctionnalité simple
\footnotesize
est_feuille(noeud)
La fonction - Problème avec cette implémentation?
bool est_feuille(noeud)
retourne
est_vide(sup_gauche(noeud)) &&
est_vide(sup_droit(noeud)) &&
est_vide(inf_gauche(noeud)) &&
est_vide(inf_droit(noeud))
. . .
- Inutile d'avoir 4 conditions (soit 4 enfants soit aucun!)
- Facile d'en oublier un!
- Comment changer la structure pour que ça soit moins terrible?
. . .
struct node
info
node enfant[4]
Structure de données
En C?
. . .
typedef struct _node {
int info;
struct _node *child[4];
} node;
is_leaf(node *tree)
?
Fonction . . .
bool is_leaf(node *tree) {
return (NULL == tree->child[0]); // only first matters
}
Problème à résoudre
- Construire un arbre quaternaire à partir d'une image:
- Créer l'arbre (allouer la mémoire pour tous les nœuds),
- Le remplir avec les valeurs des pixels.
- Compression de l'image:
- Si les pixels sont les mêmes dans le quadrant on supprime le sous-arbre (sans perte)
- Si les pixels dévient pas trop on supprime le quadrant (avec perte)
Création de l'arbre
prof
(3min)?
Comment créer un arbre de profondeur . . .
arbre creer_arbre(prof)
n = nouveau_noeud() # alloue la mémoire
si prof > 0
pour i = 0 à 3
n.enfant[i] = creer_arbre(prof-1)
retourne n
C
(3 min, matrix)?
En . . .
node *qt_create(int depth) {
node *n = calloc(1, sizeof(node));
if (depth > 0) {
for (int i = 0; i < 4; ++i) {
n->child[i] = qt_create(depth-1);
}
}
return n;
}
Le nombre de nœuds?
Comment implémenter la fonction (pseudo-code, 5min, matrix)?
. . .
entier nombre_nœuds(arbre)
si est_feuille(arbre)
retourne 1
sinon
somme = 1
pour i de 0 à 3
somme += nombre_nœuds(arbre.enfant[i])
retourne somme
Le nombre de nœuds?
Comment implémenter la fonction en C (3min, matrix)?
. . .
int size(node *qt) {
if (is_leaf(qt)) {
return 1;
} else {
int sum = 1;
for (int i = 0; i < 4; ++i) {
sum += size(qt->child[i]);
}
return sum;
}
}
La profondeur en C?
Implémentation (5min, matrix)
. . .
\footnotesize
int max(int x, int y) {
return (x >= y ? x : y);
}
int max_depth(int depths[4]) {
int m = depths[0];
for (int i = 1; i < 4; ++i) {
m = max(m, depths[i]);
}
return m;
}
int depth(node *qt) {
int depths[] = {0, 0, 0, 0};
if (is_leaf(qt)) {
return 0;
} else {
for (int i = 0; i < 4; ++i) {
depths[i] = depth(qt->child[i]);
}
return 1 + max_depth(depths);
}
}
Fonctions utiles (1/4)
Comment remplir un arbre depuis une matrice?
SG=0 | SD=1
21 | 12 | 4 | 4
9 | 7 | 4 | 4
-----------------
1 | 1 | 0 | 31
1 | 1 | 3 | 27
IG=2 | ID=3
Quel arbre cela représente?
. . .
Fonctions utiles (2/4)
- On veut transformer une ligne/colonne en feuille.
- Comment?
::: columns
:::: {.column width=40%}
ligne=2
, colonne=3
Soit SG=0 | SD=1
21 | 12 | 4 | 4
9 | 7 | 4 | 4
-----------------
1 | 1 | 0 | 31
1 | 1 | 3 | 27
IG=2 | ID=3
::::
:::: {.column width=70%}
Trouver un algorithme
- Quelle feuille pour 31 (
li=2
,co=3
)? - Plus important: quel chemin?
. . .
-
co -> G/D
,li -> S/I
, 2 * (li / 2) + co / 2 -> 2 * 1 + 1 = 3
2 * ((li % 2) / 1) + (co % 2) / 1 -> 2 * 0 + 1 = 1
- Comment généraliser?
::::
:::
Fonctions utiles (3/4)
::: columns
:::: {.column width=40%}
ligne=2
, colonne=3
Soit SG=0 | SD=1
21 | 12 | 4 | 4
9 | 7 | 4 | 4
-----------------
1 | 1 | 0 | 31
1 | 1 | 3 | 27
IG=2 | ID=3
::::
:::: {.column width=70%}
Trouver un algorithme (prendre plusieurs exemples, 15min, matrix)
- Comment généraliser?
. . .
noeud position(li, co, arbre)
d = profondeur(arbre);
tant_que (d >= 1)
index = 2 * ((li % 2^d) / 2^(d-1)) +
(col % 2^d) / 2^(d-1)
arbre = arbre.enfant[index]
d -= 1
retourne arbre
::::
:::
Fonctions utiles (4/4)
\footnotesize
Pseudo-code
noeud position(li, co, arbre)
d = profondeur(arbre);
tant_que (d >= 1)
index = 2 * ((li % 2^d) / 2^(d-1)) +
(col % 2^d) / 2^(d-1)
arbre = arbre.enfant[index]
d -= 1
retourne arbre
C
correspondant (5min, matrix)
Écrire le code
Remplir l'arbre
A partir d'une matrice (pseudo-code, 5min, matrix)?
. . .
arbre matrice_à_arbre(matrice)
arbre = creer_arbre(profondeur)
pour li de 0 à nb_lignes(matrice)
pour co de 0 à nb_colonnes(matrice)
noeud = position(li, co, arbre)
noeud.info = matrice[co][li]
retourne arbre
. . .
A partir d'une matrice (C, 5min, matrix)?
. . .
\footnotesize
node *matrix_to_qt(int nb_li, int nb_co, int matrix[nb_li][nb_co], int depth)
{
node *qt = qt_create(depth);
for (int li = 0; li < nd_li; ++li) {
for (int co = 0; co < nd_co; ++co) {
node *current = position(li, co, qt);
current->info = matrix[li][co];
}
}
return qt;
}
Remplir la matrice
A partir de l'arbre (pseudo-code, 3min, matrix)?
. . .
matrice arbre_à_matrice(arbre)
matrice = creer_matrice(nb_lignes(arbre), nb_colonnes(arbre))
pour li de 0 à nb_lignes(matrice)
pour co de 0 à nb_colonnes(matrice)
noeud = position(li, co, arbre)
matrice[co][li] = noeud.info
retourne matrice
. . .
A partir de l'arbre (C, 3min, matrix)?
. . .
\footnotesize
void qt_to_matrix(node *qt, int nb_li, int nb_co, int matrix[nb_li][nb_co])
for (int li = 0; li < nd_li; ++li) {
for (int co = 0; co < nd_co; ++co) {
node *current = position(li, co, qt);
matrix[li][co] = current->info;
}
}