diff --git a/slides/cours_13.md b/slides/cours_13.md index 304d8989e7bd929c776b012461606a643136cd9f..8160a109026436ab167679ff566152b7a1fe643e 100644 --- a/slides/cours_13.md +++ b/slides/cours_13.md @@ -220,7 +220,7 @@ bool binary_get2(int n, key_value_t table[n], key_t key, value_t *value) { . . . -* $10^{13}$ clés, $10^8$ citoyens, $10^{-5}$ ($10^{-3}\%$ de la table est +* $10^{13}$ clés, $10^7$ citoyens, $10^{-5}$ ($10^{-3}\%$ de la table est occupée) $\Rightarrow$ *inefficace*. * Pire: $10^{13}$ entrées ne rentre pas dans la mémoire d'un ordinateur. diff --git a/slides/cours_15.md b/slides/cours_15.md index 0cfc64d1aa2ac6ccfc708f19f6a4f889c3d418cc..bc4fcd0da337beb76a0af6b1b7cc43882f649b69 100644 --- a/slides/cours_15.md +++ b/slides/cours_15.md @@ -438,12 +438,12 @@ graph TD; * Appliquer une opération à tous les noeuds de l'arbre, * Nécessité de **parcourir** l'arbre, -* On utilise uniquement l'interface définie plus haut (visiter, gauche, - droite). +* Utiliser uniquement l'interface: visiter, gauche, + droite. ## Une idée de comment parcourir cet arbre? -* Trois parcours (R: Racine, G: sous-arbre gauche, D: sous-arbre droit): +* 3 parcours (R: Racine, G: sous-arbre gauche, D: sous-arbre droit): ::: columns @@ -597,6 +597,8 @@ c - a * b * d + e / f ## Live code +\footnotesize + . . . ```C @@ -647,6 +649,8 @@ parcours_infixe(arbre a) # Correction +\footnotesize + * Les deux parcours sont des modifications **triviales**[^1] de l'algorithme infixe. @@ -682,17 +686,17 @@ exercice (inspirez vous de ce qu'on a fait avant)! ## Comment imprimer l'arbre ci-dessous? ``` - f - / - e - + - d + f + / + e + + + d * - c - - - b - * - a + c + - + b + * + a ``` . . . @@ -934,112 +938,4 @@ tree_t position(tree_t tree, key_t key) { } ``` -# Code d'insertion en C (2/2) - -## Ajout du fils (ensemble) - -\scriptsize - -* 2 cas: arbre vide ou pas. -* on retourne un pointeur vers le noeud ajouté (ou `NULL`) - -. . . - -```C -tree_t add_key(tree_t *tree, key_t key) { - node_t *new_node = calloc(1, sizeof(*new_node)); // nouveauté! - new_node->key = key; - if (NULL == *tree) { - *tree = new_node; - } else { - tree_t subtree = position(*tree, key); - if (key == subtree->key) { - return NULL; - } else { - if (key > subtree->key) { - subtree->right = new_node; - } else { - subtree->left = new_node; - } - } - } - return new_node; -} -``` - -# Une nouvelle corde à votre arc! - -\footnotesize - -```C -void *calloc(size_t nmemb, size_t size); // man 3 calloc -``` - -``` -$ man 3 calloc - -The calloc() function allocates memory for an array of nmemb elements -of size bytes each and returns a pointer to the allocated memory. -The memory is set to zero. If nmemb or size is 0, then calloc() re‐ -turns either NULL, or a unique pointer value that can later be suc‐ -cessfully passed to free(). If the multiplication of nmemb and size -would result in integer overflow, then calloc() returns an error. By -contrast, an integer overflow would not be detected in the following -call to malloc(), with the result that an incorrectly sized block of -memory would be allocated: - - malloc(nmemb * size); -``` - -# La suppression de clé - -* Cas simples: le noeud à supprimer et est feuill ou a un seul fils. -* Comment faites-vous? - -. . . - -::: columns - -:::: column - -Une feuille (le 19 p.ex.). - -```mermaid -flowchart TB; - 10-->20; - 10-->5 - 20-->21 - 20-->19 -``` - -:::: - -:::: column - -Un seul fils (le 20 p.ex.). - -```mermaid -flowchart TB; - 10-->20; - 10-->5 - 20-->25 - 25-->24 - 25-->30 - 5-->4; - 5-->8; -``` - -:::: - -::: - - - - - - -## Cas compliqué - -* Le noeud à supprimer à deux descendants. - [^1]: Copyright cours de mathématiques pendant trop d'années. diff --git a/slides/cours_16.md b/slides/cours_16.md new file mode 100644 index 0000000000000000000000000000000000000000..8e6c615b7377f6ca377f91ba4b37ed12f1e0af84 --- /dev/null +++ b/slides/cours_16.md @@ -0,0 +1,1304 @@ +--- +title: "Arbres et tri par tas" +date: "2022-03-02" +patat: + eval: + tai: + command: fish + fragment: false + replace: true + ccc: + command: fish + fragment: false + replace: true + images: + backend: auto +--- + +# Un joli site + +## Visualisation d'algorithmes + +* <https://visualgo.net/> +* Allons nous rafraîchir la mémoire sur l'insertion / recherche dans un arbre + binaire. + + + +# Pseudocode d'insertion (1/2) + +* Deux parties: + * Recherche le parent où se passe l'insertion. + * Ajout du fils dans l'arbre. + +## Recherche du parent + +``` +arbre position(arbre, clé) + si est_non_vide(arbre) + si clé < clé(arbre) + suivant = gauche(arbre) + sinon + suivant = droite(arbre) + tant que clé(arbre) != clé && est_non_vide(suivant) + arbre = suivant + si clé < clé(arbre) + suivant = gauche(arbre) + sinon + suivant = droite(arbre) + + retourne arbre +``` + +# Pseudocode d'insertion (2/2) + +* Deux parties: + * Recherche de la position. + * Ajout dans l'arbre. + +## Ajout du fils + +``` +ajout(arbre, clé) + si est_vide(arbre) + arbre = noeud(clé) + sinon + arbre = position(arbre, clé) + si clé < clé(arbre) + gauche(arbre) = noeud(clé) + sinon si clé > clé(arbre) + droite(arbre) = noeud(clé) + sinon + retourne +``` + +# Code d'insertion en C (1/2) + +## Recherche du parent (ensemble) + +. . . + +```C +tree_t position(tree_t tree, key_t key) { + tree_t current = tree; + if (NULL != current) { + tree_t subtree = key > current->key ? current->right : + current->left; + while (key != current->key && NULL != subtree) { + current = subtree; + subtree = key > current->key ? current->right : + current->left; + } + } + return current; +} +``` + +# Code d'insertion en C (2/2) + +## Ajout du fils (ensemble) + +\scriptsize + +* 2 cas: arbre vide ou pas. +* on retourne un pointeur vers le noeud ajouté (ou `NULL`) + +. . . + +```C +tree_t add_key(tree_t *tree, key_t key) { + node_t *new_node = calloc(1, sizeof(*new_node)); // nouveauté! + new_node->key = key; + if (NULL == *tree) { + *tree = new_node; + } else { + tree_t subtree = position(*tree, key); + if (key == subtree->key) { + return NULL; + } else { + if (key > subtree->key) { + subtree->right = new_node; + } else { + subtree->left = new_node; + } + } + } + return new_node; +} +``` + +# Une nouvelle corde à votre arc! + +\footnotesize + +```C +void *calloc(size_t nmemb, size_t size); // man 3 calloc +``` + +``` +$ man 3 calloc + +The calloc() function allocates memory for an array of nmemb elements +of size bytes each and returns a pointer to the allocated memory. +The memory is set to zero. If nmemb or size is 0, then calloc() re‐ +turns either NULL, or a unique pointer value that can later be suc‐ +cessfully passed to free(). If the multiplication of nmemb and size +would result in integer overflow, then calloc() returns an error. By +contrast, an integer overflow would not be detected in the following +call to malloc(), with the result that an incorrectly sized block of +memory would be allocated: + + malloc(nmemb * size); +``` + +# La suppression de clé + + +. . . + +::: columns + +:::: column + +## Cas simples: + +* le noeud est absent, +* le noeud est une feuille +* le noeuds a un seul fils. + +## Une feuille (le 19 p.ex.). + +```{.mermaid format=pdf width=400 loc=figs/} +flowchart TB; + 10-->20; + 10-->5 + 20-->21 + 20-->19 +``` + +:::: + +:::: column + +## Un seul fils (le 20 p.ex.). + +```{.mermaid format=pdf width=400 loc=figs/} +flowchart TB; + 10-->20; + 10-->5 + 20-->25 + 20-->18 + 25-->24 + 25-->30 + 5-->4; + 5-->8; + style 18 fill:#fff,stroke:#fff,color:#fff +``` + +## Dans tous les cas + +* Chercher le noeud à supprimer: utiliser `position()`. + +:::: + +::: + +# La suppression de clé + + +::: columns + +:::: column + +## Cas compliqué + +* Le noeud à supprimer à (au moins) deux descendants (10). + +```{.mermaid format=pdf width=400 loc=figs/} +flowchart TB; + 10-->20; + 10-->5 + 20-->25 + 20-->18 + 25-->24 + 25-->30 + 5-->4; + 5-->8; +``` + +:::: + +:::: column + +* Si on enlève 10 il se passe quoi? +* On peut pas juste enlever `10` et recoller... +* Proposez une solution bon sang! + +. . . + +## Solution + +* Échange de la valeur à droite dans le sous-arbre de gauche ou + ... +* de la valeur de gauche dans le sous-arbre de droite! +* Puis, on retire le noeud. + +:::: + +::: + +# Le pseudo-code de la suppression + +## Pour une feuille ou absent (ensemble) + +``` +arbre suppression(arbre, clé) + sous_arbre = position(arbre, clé) + si est_vide(sous_arbre) ou clé(sous_arbre) != clé + retourne vide + sinon + si est_feuille(sous_arbre) et clé(sous_arbre) == clé + nouvelle_feuille = parent(arbre, sous_arbre) + si est_vide(nouvelle_feuill) + arbre = vide + sinon + si gauche(nouvelle_feuille) == sous_arbre + gauche(nouvelle_feuille) = vide + sinon + droite(nouvelle_feuille) = vide + retourne sous_arbre +``` + +# Il nous manque le code pour le `parent` + +## Pseudo-code pour trouver le parent (5min -> matrix) + +``` +arbre parent(arbre, sous_arbre) + si est_non_vide(arbre) + actuel = arbre + clé = clé(sous_arbre) + faire + parent = actuel + si (clé != clé(actuel)) + si clé < clé(actuel) + actuel = gauche(actuel) + sinon + actuel = droite(actuel) + sinon + retour parent + tant_que (actuel != sous_arbre) + retourne vide +``` + +# Le pseudo-code de la suppression + +## Pour un seul enfant (5min -> matrix) + +``` +arbre suppression(arbre, clé) + sous_arbre = position(arbre, clé) + si est_vide(gauche(sous_arbre)) ou est_vide(droite(sous_arbre)) + parent = parent(arbre, sous_arbre) + si est_vide(gauche(sous_arbre)) + si droite(parent) == sous_arbre + droite(parent) = droite(sous_arbre) + sinon + gauche(parent) = droite(sous_arbre) + sinon + si droite(parent) == sous_arbre + droite(parent) = gauche(sous_arbre) + sinon + gauche(parent) = gauche(sous_arbre) + retourne sous_arbre +``` + + +# Le pseudo-code de la suppression + +## Pour au moins deux enfants (ensemble) + +``` +arbre suppression(arbre, clé) + sous_arbre = position(arbre, clé) # on revérifie pas que c'est bien la clé + si est_non_vide(gauche(sous_arbre)) et est_non_vide(droite(sous_arbre)) + max_gauche = position(sous_arbre, clé) + échange(clé(max_gauche), clé(sous_arbre)) + suppression(sous_arbre, clé) # +``` + +# Exercices (poster sur matrix) + +1. Écrire le pseudo-code de l'insertion purement en récursif. + +. . . + +``` +arbre insertion(arbre, clé) + si est_vide(arbre) + retourne noeud(clé) + + si (clé < arbre->clé) + gauche(arbre) = insert(gauche(arbre), clé) + sinon + droite(arbre) = insert(droite(arbre), clé) + retourne arbre +``` + +# Exercices (poster sur matrix) + +2. Écrire le pseudo-code de la recherche purement en récursif. + +. . . + +``` +bool recherche(arbre, clé) + si est_vide(arbre) + retourne faux // pas trouvée + si clé(arbre) == clé + retourne vrai // trouvée + si clé < clé(arbre) + retourne recherche(gauche(arbre), clé) + sinon + retourne recherche(droite(arbre), clé) +``` + +#Exercices (à la maison) + +3. Écrire une fonction qui insère des mots dans un arbre et ensuite affiche + l'arbre. + +# Trier un tableau à l'aide d'un arbre binaire + +* Tableau représenté comme un arbre binaire. +* Aide à comprendre "comment" trier, mais on ne construit jamais l'arbre. +* Complexité $O(N\log_2 N)$ en moyenne et grande stabilité (pas de cas + dégénérés). + +# Lien entre arbre et tableau + +* La racine de l'arbre set le premier élément du tableau. +* Les deux fils d'un noeud d'indice $i$, ont pour indices $2i+1$ et $2i+2$: + * Les fils du noeud $i=0$, sont à $2\cdot 0+1=1$ et $2\cdot 0+2=2$. + * Les fils du noeud $i=1$, sont à $2\cdot 1+1=3$ et $2\cdot 1+2=4$. + * Les fils du noeud $i=2$, sont à $2\cdot 2+2=5$ et $2\cdot 1+2=6$. + * Les fils du noeud $i=3$, sont à $2\cdot 3+1=7$ et $2\cdot 3+2=8$. +* Un élément d'indice $i$ a pour parent l'élément $(i-1)/2$ (division entière): + * Le parent du noeud $i=8$ est $(8-1)/2=3$. + * Le parent du noeud $i=7$ est $(7-1)/2=3$. + +# Visuellement + +::: columns + +:::: column + +* Où vont les indices correspondant du tableau? + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0(( ))-->id1(( )); + id0-->id2(( )); + id1-->id3(( )); + id1-->id4(( )); + id2-->id5(( )); + id2-->id6(( )); + id3-->id7(( )); + id3-->id8(( )); + id4-->id9(( )); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` +:::: + +:::: column + +* Les flèche de gauche à droite, parent -> enfants. +* Les flèche de droite à gauche, enfants -> parent. + + + +:::: + +::: + +**Propriétés:** + +1. les feuilles sont toutes sur l'avant dernier ou dernier niveau. +2. les feuilles de profondeur maximale sont "tassée" à gauche. + +# Le tas (ou heap) + +## Définition + +* Un arbre est un tas, si la valeur de chacun de ses descendants est inférieure + ou égale à sa propre valeur. + +## Exemples (ou pas) + +``` +16 8 14 6 2 10 12 4 5 # Tas +16 14 8 6 2 10 12 4 5 # Non-tas, 10 > 8 et 12 > 8 +``` + +## Exercices (ou pas) + +``` +19 18 12 12 17 1 13 4 5 # Tas ou pas tas? +19 18 16 12 17 1 12 4 5 # Tas ou pas tas? +``` + +. . . + +``` +19 18 12 12 17 1 13 4 5 # Pas tas! 13 > 12 +19 18 16 12 17 1 12 4 5 # Tas! +``` + +# Exemple de tri par tas (1/N) + +``` + | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 | +``` + +::: columns + +:::: column + +* Quel est l'arbre que cela représente? + +. . . + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((5)); + id1-->id3((12)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6((8)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((7)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Transformer l'arbre en tas. + +* On commence à l'indice $N/2 = 5$: `7`. +* `7 > 4` (enfant `>` parent). +* intervertir `4` et `7`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((5)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((8)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +::: + +. . . + +``` + * * + | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 | +``` + +# Exemple de tri par tas (2/N) + +``` + | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 | +``` + +::: columns + +:::: column + +**But:** Transformer l'arbre en tas. + +* On continue à l'indice $N/2-1 = 4$: `12`. +* Déjà un tas, rien à faire. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((5)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((8)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Transformer l'arbre en tas. + +* On continue à l'indice $N/2-2 = 3$: `5`. +* `5 < 8`, échanger `8` et `5` (aka `max(2, 5, 8)`) + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((8)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +::: + +. . . + +``` + | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 | +``` + +# Exemple de tri par tas (3/N) + +``` + | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 | +``` + +::: columns + +:::: column + +**But:** Transformer l'arbre en tas. + +* Indice $N/2-1 = 4$: `12`. +* Déjà un tas, rien à faire. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((5)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((8)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Transformer l'arbre en tas. + +* Indice $N/2-2 = 3$: `5`. +* `5 < 8`, `5 <=> max(2, 5, 8)` + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((8)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + * * + | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 | +``` + +# Exemple de tri par tas (4/N) + +``` + | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 | +``` + +::: columns + +:::: column + +**But:** Transformer l'arbre en tas. + +* Indice $N/2-3 = 1$: `16`. +* Déjà un tas, rien à faire. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((16)); + id0-->id2((8)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Transformer l'arbre en tas. + +* Indice $N/2-4 = 1$: `1`. +* `1 < 16 && 1 < 8`, `1 <=> max(1, 16, 8)` + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((16))-->id1((1)); + id0-->id2((8)); + id1-->id3((12)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + * * + | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 | +``` + + +# Exemple de tri par tas (5/N) + +``` + | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 | +``` + +::: columns + +:::: column + +**But:** Transformer l'arbre en tas. + +* Recommencer avec `1`. +* `1 <=> max(1, 12, 7)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((16))-->id1((12)); + id0-->id2((8)); + id1-->id3((1)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((10)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Transformer l'arbre en tas. + +* Recommencer avec `1`. +* `1 <=> max(1, 10, 6)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((16))-->id1((12)); + id0-->id2((8)); + id1-->id3((10)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((1)); + id3-->id8((6)); + id4-->id9((4)); + id4-->id10(( )); + style id10 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + * * * + | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 | +``` + +* L'arbre est un tas. + +# Exemple de tri par tas (6/N) + +``` + | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 | +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `16` (`max` de l'arbre) avec `4`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((4))-->id1((12)); + id0-->id2((8)); + id1-->id3((10)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((1)); + id3-->id8((6)); +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `4 <=> max(4, 12, 8)`. +* `4 <=> max(4, 10, 7)`. +* `4 <=> max(4, 1, 6)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((12))-->id1((10)); + id0-->id2((8)); + id1-->id3((6)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((1)); + id3-->id8((4)); +``` + +:::: + +::: + +``` + | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16 +``` + + +# Exemple de tri par tas (7/N) + +``` + | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `12` (`max` de l'arbre) avec `4`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((4))-->id1((10)); + id0-->id2((8)); + id1-->id3((6)); + id1-->id4((7)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((1)); + id3-->id8(( )); + style id8 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `4 <=> max(4, 10, 8)`. +* `4 <=> max(4, 6, 7)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((10))-->id1((7)); + id0-->id2((8)); + id1-->id3((6)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6((5)); + id3-->id7((1)); + id3-->id8(( )); + style id8 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16 +``` + +# Exemple de tri par tas (8/N) + +``` + | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `10` (`max` de l'arbre) avec `1`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((7)); + id0-->id2((8)); + id1-->id3((6)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6((5)); +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `1 <=> max(1, 7, 8)`. +* `5 <=> max(1, 2, 5)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((8))-->id1((7)); + id0-->id2((5)); + id1-->id3((6)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6((1)); +``` + +:::: + +::: + +``` + | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16 +``` + +# Exemple de tri par tas (9/N) + +``` + | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `8` (`max` de l'arbre) avec `1`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((7)); + id0-->id2((5)); + id1-->id3((6)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6(( )); + style id6 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `1 <=> max(1, 7, 5)`. +* `1 <=> max(1, 6, 4)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((7))-->id1((6)); + id0-->id2((5)); + id1-->id3((1)); + id1-->id4((4)); + id2-->id5((2)); + id2-->id6(( )); + style id6 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16 +``` + +# Exemple de tri par tas (10/N) + +``` + | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `7` (`max` de l'arbre) avec `2`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((2))-->id1((6)); + id0-->id2((5)); + id1-->id3((1)); + id1-->id4((4)); +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `2 <=> max(2, 6, 5)`. +* `2 <=> max(2, 1, 4)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((6))-->id1((4)); + id0-->id2((5)); + id1-->id3((1)); + id1-->id4((2)); +``` + +:::: + +::: + +``` + | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16 +``` + +# Exemple de tri par tas (11/N) + +``` + | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `6` (`max` de l'arbre) avec `2`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((2))-->id1((4)); + id0-->id2((5)); + id1-->id3((1)); + id1-->id4(( )); + style id4 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `2 <=> max(2, 4, 5)`. +* `2 <=> max(2, 1, 4)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((5))-->id1((4)); + id0-->id2((2)); + id1-->id3((1)); + id1-->id4(( )); + style id4 fill:#fff,stroke:#fff +``` + +:::: + +::: + +``` + | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16 +``` + +# Exemple de tri par tas (12/N) + +``` + | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `5` (`max` de l'arbre) avec `1`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((1))-->id1((4)); + id0-->id2((2)); +``` + +:::: + +:::: column + +**But:** Trier les tas. + +* `1 <=> max(1, 4, 2)`. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((4))-->id1((1)); + id0-->id2((2)); +``` + +:::: + +::: + +``` + | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16 +``` + +# Exemple de tri par tas (13/N) + +``` + | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16 +``` + +::: columns + +:::: column + +**But:** Trier les tas. + +* Échanger la racine, `4` (`max` de l'arbre) avec `2`. +* Traiter la racine. + +```{.mermaid format=pdf width=400 loc=figs/} +graph TD; + id0((2))-->id1((1)); + id0-->id2(( )); + style id2 fill:#fff,stroke:#fff +``` + +:::: + +:::: column + +**But:** Trier les tas. Plus rien à trier + +* On fait les 2 dernières étapes en vitesse. +* Échange `2` avec `1`. +* Il reste que `1`. GGWP! + + +:::: + +::: + +``` + | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16 +``` + +# Exercice (10min) + +* Trier par tas le tableau + +``` + | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16 +``` + +* Mettez autant de détails que possible. +* Que constatez-vous? +* Postez le résultat sur matrix. + + +# L'algorithme du tri par tas (1/4) + +## Deux étapes + +1. Entassement (tamisage): transformer l'arbre en tas. +2. Échanger la racine avec le dernier élément et entasser la racine. + +## Pseudo-code d'entassement de l'arbre (5 min, matrix) + +. . . + +``` +tri_par_tas(tab) + entassement(tab) + échanger(tab[0], tab[size(tab)-1]) + pour i = size(tab)-1 à 2 + promotion(tab, i) + échanger(tab[0], tab[i-1]) +entassement(tab) + pour i = size(tab) / 2 - 1 jusqu'à 0 + promotion(tab, i) +promotion(tab, i) + ind_max = ind_max(tab, i, gauche(i), droite(i)) + si i != ind_max + échanger(tab[i], tab[ind_max]) + promotion(tab, ind_max) +``` + +# L'algorithme du tri par tas (2/4) + +* Fonctions utilitaires + +``` +int ind_max(tab, i, g, d) + ind_max = i + si tab[ind_max] < tab[l] + ind_max = l + si tab[ind_mx] < tab[r] + ind_max = r + retourne ind_max +int gauche(i) + retourne 2 * i + 1 +int droite(i) + retourne 2 * i + 2 +``` + + +# L'algorithme du tri par tas (3/4) + +\footnote size + +## Implémenter en C l'algorithme du tri par tas (matrix, 20min) + +. . . + +```C +void heapsort(int size, int tab[size]) { + heapify(size, tab); + swap(tab, tab + size - 1); + for (int s = size - 1; s > 1; s--) { + sift_up(s, tab, 0); + swap(tab, tab + s - 1); + } +} +void heapify(int size, int tab[size]) { + for (int i = size / 2 - 1; i >= 0; i--) { + sift_up(size, tab, i); + } +} +void sift_up(int size, int tab[size], int i) { + int ind_max = ind_max3(size, tab, i, left(i), right(i)); + if (i != ind_max) { + swap(tab + i, tab + ind_max); + sift_up(size, tab, ind_max); + } +} +``` + +# L'algorithme du tri par tas (3/4) + +\footnotesize + +## Fonctions utilitaires + +. . . + +```C +int ind_max3(int size, int tab[size], int i, int l, int r) { + int ind_max = i; + if (l < size && tab[ind_max] < tab[l]) { + ind_max = l; + } + if (r < size && tab[ind_max] < tab[r]) { + ind_max = r; + } + return ind_max; +} +void swap(int *a, int *b) { + int tmp = *a; + *a = *b; + *b = tmp; +} +int left(int i) { + return 2 * i + 1; +} +int right(int i) { + return 2 * i + 2; +} +``` diff --git a/slides/figs/heap_tree.svg b/slides/figs/heap_tree.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2686fff1a419dfe835615eb6383aee03bc70daf --- /dev/null +++ b/slides/figs/heap_tree.svg @@ -0,0 +1,498 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="159.01459mm" + height="65.378784mm" + viewBox="0 0 159.01459 65.378784" + version="1.1" + id="svg5" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + sodipodi:docname="heap_tree.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview7" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="true" + inkscape:zoom="0.67081229" + inkscape:cx="168.45249" + inkscape:cy="78.263325" + inkscape:window-width="1920" + inkscape:window-height="1080" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0"> + <inkscape:grid + type="xygrid" + id="grid824" + originx="-26.326043" + originy="-41.90753" /> + </sodipodi:namedview> + <defs + id="defs2"> + <marker + style="overflow:visible" + id="Arrow2Lend" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-2" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-0" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8-2" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7-3" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8-2-9" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7-3-2" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-2-2" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-0-8" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8-3" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7-6" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-1" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-2" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-1-9" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-2-4" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8-3-7" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7-6-8" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-1-0" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-2-3" /> + </marker> + <marker + style="overflow:visible" + id="Arrow2Lend-8-3-6" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Lend" + inkscape:isstock="true"> + <path + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round" + id="path17053-7-6-1" /> + </marker> + </defs> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-26.326042,-41.907531)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="31.369009" + y="64.637695" + id="text2487"><tspan + sodipodi:role="line" + id="tspan2485" + style="stroke-width:0.264583" + x="31.369009" + y="64.637695">0</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 26.458333,68.791666 h 15.875 V 52.916667 h -15.875 v 15.875" + id="path15418" /> + <g + id="g15829" + transform="translate(-5.2916667,-26.458334)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="53.213009" + y="91.090736" + id="text4987"><tspan + sodipodi:role="line" + id="tspan4985" + style="stroke-width:0.264583" + x="53.213009" + y="91.090736">1</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 47.625,95.25 H 63.5 V 79.375001 H 47.625 v 15.875" + id="path15418-3" /> + </g> + <g + id="g15834" + transform="translate(-37.041667,-52.916673)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="100.18185" + y="117.60199" + id="text5981"><tspan + sodipodi:role="line" + id="tspan5979" + style="stroke-width:0.264583" + x="100.18185" + y="117.60199">2</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 95.25,121.70833 h 15.875 V 105.83334 H 95.25 v 15.87499" + id="path15418-6" /> + </g> + <g + id="g15839" + transform="translate(-58.208327,-58.208333)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="137.26584" + y="122.84074" + id="text6887"><tspan + sodipodi:role="line" + id="tspan6885" + style="stroke-width:0.264583" + x="137.26584" + y="122.84074">3</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 132.29166,127 h 15.875 v -15.875 h -15.875 V 127" + id="path15418-7" /> + </g> + <g + id="g15844" + transform="translate(-42.333327,-74.083333)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="137.19705" + y="138.73691" + id="text7815"><tspan + sodipodi:role="line" + id="tspan7813" + style="stroke-width:0.264583" + x="137.19705" + y="138.73691">4</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 132.29166,142.875 h 15.875 V 127 h -15.875 v 15.875" + id="path15418-5" /> + </g> + <g + id="g15854" + transform="translate(111.125,-68.791663)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="15.451676" + y="133.42407" + id="text9407"><tspan + sodipodi:role="line" + id="tspan9405" + style="stroke-width:0.264583" + x="15.451676" + y="133.42407">6</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 10.583333,137.58333 h 15.875 v -15.87499 h -15.875 v 15.87499" + id="path15418-35" /> + </g> + <g + id="g15849" + transform="translate(79.375,-58.208333)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="31.337259" + y="122.78782" + id="text8479"><tspan + sodipodi:role="line" + id="tspan8477" + style="stroke-width:0.264583" + x="31.337259" + y="122.78782">5</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 26.458333,127 h 15.875 v -15.875 h -15.875 V 127" + id="path15418-62" /> + </g> + <g + id="g15859" + transform="translate(58.208333,-100.54167)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="84.312134" + y="165.17407" + id="text10533"><tspan + sodipodi:role="line" + id="tspan10531" + style="stroke-width:0.264583" + x="84.312134" + y="165.17407">7</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 79.375,169.33334 H 95.25 v -15.875 H 79.375 v 15.875" + id="path15418-9" /> + </g> + <g + id="g15864" + transform="translate(121.70833,-111.125)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="36.66597" + y="175.7574" + id="text11329"><tspan + sodipodi:role="line" + id="tspan11327" + style="stroke-width:0.264583" + x="36.66597" + y="175.7574">8</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 31.75,179.91667 h 15.875 v -15.875 H 31.75 v 15.875" + id="path15418-1" /> + </g> + <g + id="g15869" + transform="translate(153.45833,-116.41667)"> + <text + xml:space="preserve" + style="font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583" + x="20.796259" + y="181.04907" + id="text13137"><tspan + sodipodi:role="line" + id="tspan13135" + style="stroke-width:0.264583" + x="20.796259" + y="181.04907">9</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 15.875,185.20834 H 31.75 v -15.875 H 15.875 v 15.875" + id="path15418-2" /> + </g> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 26.458333,68.791666 v 21.166666 l 158.749997,10e-7 V 68.791667" + id="path15904" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 42.333333,68.791666 V 89.958332" + id="path15906" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 58.208333,68.791667 v 21.16666" + id="path15906-7" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 74.083333,68.791667 V 89.958329" + id="path15906-0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 89.958333,68.791667 v 21.16666" + id="path15906-9" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 121.70833,68.791667 v 21.16666" + id="path15906-3" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 137.58333,68.791667 v 21.16666" + id="path15906-6" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 153.45833,68.791667 v 21.16666" + id="path15906-06" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 169.33333,68.791667 v 21.16666" + id="path15906-2" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 105.83333,68.791667 v 21.16667" + id="path15906-61" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)" + d="m 34.395833,50.270833 c 0,0 7.9375,-10.583334 15.875,0" + id="path16437" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-8)" + d="m 34.395833,50.270833 c 0,0 14.552084,-18.520833 31.75,0" + id="path16437-9" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-1)" + d="m 161.39583,91.28125 c 0,0 -38.36458,35.71875 -79.374997,0" + id="path16437-93" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-8-3)" + d="m 145.52083,91.28125 c 0,0 -31.75,21.16667 -60.854163,0" + id="path16437-9-1" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-1-0)" + d="m 129.64583,91.28125 c 0,0 -31.749997,34.39583 -62.17708,0" + id="path16437-93-0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-8-3-6)" + d="m 113.77083,91.28125 c 0,0 -23.812497,21.16667 -43.656247,0" + id="path16437-9-1-6" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-2)" + d="m 50.270836,50.270833 c 0,0 15.874997,-10.583333 31.749997,0" + id="path16437-7" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-8-2)" + d="m 50.270836,50.270833 c 0,0 23.812497,-18.520833 47.624997,0" + id="path16437-9-5" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-2-2)" + d="m 66.145833,50.270833 c 0,0 23.8125,-11.90625 47.624997,1.322917" + id="path16437-7-9" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-8-2-9)" + d="m 66.145833,50.270833 c 0,0 31.75,-18.520833 62.177087,0" + id="path16437-9-5-7" + sodipodi:nodetypes="cc" /> + </g> +</svg>