From b7a82223d2f679bf9fd4d4d0dc9ee6497109000d Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Mon, 6 May 2024 14:57:15 +0200 Subject: [PATCH] maj 2024 --- slides/cours_23.md | 1608 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1608 insertions(+) create mode 100644 slides/cours_23.md diff --git a/slides/cours_23.md b/slides/cours_23.md new file mode 100644 index 0000000..a08b412 --- /dev/null +++ b/slides/cours_23.md @@ -0,0 +1,1608 @@ +--- +title: "Les B-arbres et graphes" +date: "2024-05-07" +--- + +# Les B-arbres + +\Huge + +Les B-arbres + + +# Les B-arbres + +## Problématique + +* Grands jeux de données (en 1970). +* Stockage dans un arbre, mais l'arbre tiens pas en mémoire. +* Regrouper les sous-arbres en **pages** qui tiennent en mémoire. + +## Exemple + +* 100 nœuds par page et l'arbre comporte $10^6$ nœuds: + * Recherche B-arbre: $\log_{100}(10^6)=3$; + * Recherche ABR: $\log_2(10^6)=20$. +* Si on doit lire depuis le disque: $10\mathrm{ms}$ par recherche+lecture: + * $30\mathrm{ms}$ (lecture beaucoup plus rapide que recherche) vs $200\mathrm{ms}=0.2\mathrm{s}$. + +## Remarques + +* On sait pas ce que veut dire `B`: Bayer, Boeing, Balanced? +* Variante plus récente B+-arbres. + +# Les B-arbres + +## Illustration, arbre divisé en pages de 3 nœuds + + + +. . . + +## Utilisation + +* Bases de données (souvent très grandes donc sur le disque); +* Système de fichier. + +# Les B-arbres + +## Avantages + +* Arbres moins profonds; +* Diminue les opération de rééquilibrage; +* Complexité toujours en $\log(N)$; + +. . . + +## Définition: B-arbre d'ordre $n$ + +* 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. + +# Les B-arbres + +## Est-ce un B-arbre? + + + +. . . + +## Oui! + +* Dans chaque nœud les clés sont **triées**. +* Chaque page contient au plus $n$ nœuds: check; +* Chaque nœud avec $m$ clés a $m+1$ descendants; +* Toutes les feuilles apparaissent au même niveau. + +# Les B-arbres + +## Exemple de recherche: trouver `32` + + + +. . . + +* Si `n` plus petit que la 1e clé ou plus grand que la dernière descendre. +* Sinon parcourir (par bissection ou séquentiellement) jusqu'à trouver ou descendre entre 2 éléments. + +# Les B-arbres + +## La recherche de la clé `C` algorithme + +0. En partant de la racine. +1. Si on est dans une feuille: + * Si la `C` est dans une page, retourner la page; + * Sinon c'est perdu. +2. Sinon: + * Tant que `C > page` passer à la page suivante + * Descendre + +# Les B-arbres + +## Disclaimer + +* Inspiration de <https://en.wikipedia.org/wiki/B-tree> + +## Exemples d'insertion: `1` + + + +. . . + +* L'arbre est vide, on insère juste dans la première page. + +# Les B-arbres + +## Exemples d'insertion: `2` + + + +. . . + +* La première page est pas pleine, on insère dans l'ordre (après 1). + +# Les B-arbres + +## Exemples d'insertion: `3` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `3` + +{width=50%} + +. . . + +* La page est pleine, on crée deux enfants. +* On choisit, `2`, la médiane de `1, 2, 3` et il est inséré à la racine. +* `1` descend à gauche, `3` descend à droite. + +# Les B-arbres + +## Exemples d'insertion: `4` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `4` + +{width=50%} + +. . . + +* On pourrait insérer à droite de `2`, mais... ça ferait 2 parents pour 2 enfants (mais `m` parents => `m+1` enfants ou `0`); +* On descend à droite (`4 > 2`); +* On insère à droite de `3`. + +# Les B-arbres + +## Exemples d'insertion: `5` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `5` + + + +. . . + +* On descend à droite (on peut pas insérer à la racine comme pour `4`); +* On dépasse la capacité de l'enfant droite; +* `4`, médiane de `3, 4, 5`, remonte à la racine; +* On crée un nouveau nœud à droite de `4`; +* La règle `m => m+1` est ok. + +# Les B-arbres + +## Exemples d'insertion: `6` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `6` + + + +. . . + +* `6 > 4` on descend à droite; +* `6 > 5` et on a à la place à droite, on insère. + +# Les B-arbres + +## Exemples d'insertion: `7` + +{width=50%} + +* Comment on insère (1min de réflexion avant de donner une réponse!)? + +# Les B-arbres + +## Exemples d'insertion: `7` + +{width=50%} + +. . . + +* `7 > 4` on descend à droite; +* `7 > 6` mais on a dépassé la capacité; +* `6` est la médiane de `5, 6, 7`, remonte à la racine; +* `5` reste à gauche, `7` à droite, mais `6` fait dépasser la capacité de la racine; +* `4` est la médiane de `2, 4, 6`, `4` remonte, `2` reste à gauche, `6` à droite. + +# Les B-arbres + +## L'algorithme d'insertion + +0. Rechercher la feuille (la page a aucun enfant) où insérer; +1. Si la page n'est pas pleine insérer dans l'ordre croissant. +2. Si la page est pleine, on sépare la page en son milieu : + 1. On trouve la médiane, `M`, de la page; + 2. On met les éléments `< M` dans la page de gauche de `M` et les `> M` dans la page de droite de `M`; + 3. `M` est insérée récursivement dans la page parent. + +# Les B-arbres + +## Exercice: insérer `22, 45, 50` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + + +# Les B-arbres + +## Exercice: insérer `5` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice: insérer `32, 55, 60` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice: insérer `41` dans l'arbre d'ordre 2 (3min matrix) + + + +. . . + + + +# Les B-arbres + +## Exercice (matrix, 15min) + +* Insérer 20, 40, 10, 30, 15, 35, 7, 26, 18, 22, 5, 42, 13, 46, 27, 8, 32, 38, 24, 45, 25, 2, 14, 28, 32, 41, +* Dans un B-arbre d'ordre 2. + +# 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 mais `m` clés. +* Comment faire pour gérer l'insertion? + +# Les B-arbres + +## Faire un dessin de la structure de données (3min matrix)? + +. . . + + + +1. On veut un tableau de `P_i, K_i => struct`; +2. `K_0` va être en "trop"; +3. Pour simplifier l'insertion dans une page, on ajoute un élément de plus. + +# Les B-arbres + +## L'insertion cas nœud pas plein, insertion `4`? + +{width=50%} + +. . . + +## Solution + +{width=50%} + +# Les B-arbres + +## L'insertion cas nœud pas plein, insertion `N` + +* 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 + +## L'insertion cas nœud plein, insertion `2`? + +{width=50%} + +. . . + +## Solution + +{width=50%} + +# Les B-arbres + +## L'insertion cas nœud plein, promotion `3`? + +{width=50%} + +. . . + +## Solution + + + +# Les B-arbres + +## L'insertion cas nœud plein, insertion `N` + +* 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 de `M` avec l'ancienne et la nouvelle page respectivement. + +# Les B-arbres + +## Pseudo-code structure de données (3min, matrix)? + +. . . + +```C +struct page + entier ordre, nb + element tab[2*ordre + 2] +``` + +```C +struct element + entier clé + page pg +``` + +# Les B-arbres + +\footnotesize + +## Les fonctions utilitaires (5min matrix) + +```C +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 +``` + +. . . + +```C +booléen est_feuille(page) + retourne (page.tab[0].pg == vide) + +entier position(page, valeur) + i = 0 + tant que i < page.nb && valeur >= 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) + +```C +page nouvelle_page(ordre) // créer une page +rien liberer_memoire(page) // libérer tout un arbre! +``` +. . . + +```C +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) + +```C +page recherche(page, valeur) // retourner la page contenant + // la valeur ou vide +``` + +. . . + +```C +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) - 1], valeur) +``` + +# Les B-arbres + +## Les fonctions + +```C +page inserer_valeur(page, valeur) // insérer une valeur +``` + +. . . + +```C +page inserer_valeur(page, valeur) + element = nouvel_element(valeur) + // ici élément est modifié 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 + +```C +rien inserer_element(page, element) // insérer un element + // et voir s'il remonte +``` + +. . . + +```C +rien inserer_element(page, element) + si est_feuille(page) + placer(page, element) + sinon + sous_page = page.tab[position(page, element.clé) - 1].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) + +```C +rien placer(page, element) // inserer un élément +``` + +. . . + +```C +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) + +```C +rien scinder(page, element) // casser une page et remonter +``` + +. . . + +```C +rien scinder(page, element) + nouvelle_page = nouvelle_page(page.ordre) + nouvelle_page.nb = page.ordre + pour i de 0 à ordre inclu + nouvelle_page.tab[i] = page.tab[i+ordre+1] + element.clé = page.tab[ordre+1].clé + element.page = nouvelle_page +``` + +# Les B-arbres + +## Les fonctions (5min matrix) + +```C +page ajouter_niveau(page, element) // si on remonte à la + // racine, on doit créer + // une nouvelle racine +``` + +. . . + +```C +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 --> + +<!-- ## Structure de données en C (3min, matrix) --> + +<!-- . . . --> + +<!-- ```C --> +<!-- typedef struct _page { --> +<!-- int order, nb; --> +<!-- struct _element *tab; --> +<!-- } page; --> +<!-- ``` --> + +<!-- ```C --> +<!-- typedef struct element { --> +<!-- int key; --> +<!-- struct _page *pg; --> +<!-- } element; --> +<!-- ``` --> + + +# Les B-arbres: suppression + +## Cas simplissime + +{width=80%} + +. . . + +{width=80%} + +# Les B-arbres: suppression + +\footnotesize + +## Cas simple + + +{width=60%} + +. . . + +* 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? + +. . . + +{width=60%} + +# Les B-arbres: suppression + +## Cas moins simple + +{width=60%} + +. . . + +* Un élément à droite, comment on fait? + * Remonter `7`, serait ok si racine, mais... c'est pas forcément. + * On redistribue les feuilles. + +. . . + +{width=60%} + +# Les B-arbres: suppression + +\footnotesize + +## Cas ultra moins simple + +{width=60%} + +. . . + +* `7` seul: + * Fusionner les feuilles et redistribuer, comment? + +. . . + +{width=60%} + +# Les B-arbres: suppression + +## Cas ultra moins simple + +{width=60%} + +. . . + +* `8` est seul, c'est plus un B-arbre : + * Fusionner le niveau 2 et redistribuer, comment? + +. . . + +{width=40%} + +. . . + +* La profondeur a diminué de 1. + +# Les B-arbres: suppression + +## Algorithme pour les feuilles! + +* Si la clé est supprimée d'une feuille: + * Si on a toujours `n` (ordre de l'arbre) clés dans la feuille on décale simplement les clés. + * Sinon on combine (récursivement) avec le nœud voisin et on descend la clé médiane. + +# Les B-arbres: suppression + +## Cas non-feuille! + +{width=60%} + +. . . + +* On sait comment effacer une valeur d'une feuille, donc? + +. . . + +{width=60%} + +* Ensuite? + +# Les B-arbres: suppression + +## Cas non-feuille! + +{width=60%} + +. . . + +* On sait comment effacer une valeur d'une feuille! + +. . . + +{width=60%} + +# Les B-arbres: suppression + +## Algorithme pour les non-feuilles! + +* Si la clé est supprimée d'une page qui n'est pas une feuille: + * On échange la valeur avec la valeur de droite de la page de gauche + * On supprime comme pour une feuille! + +## Et maintenant des exercices par millions! + +# Les graphes + +\Huge + +Les graphes + +# Les graphes! Historique + +**Un mini-peu d'histoire...** + +## L. Euler et les 7 ponts de Koenigsberg: + +* Existe-t-il une promenade sympa, passant **une seule fois** par les 7 ponts et revenant au point de départ? + +{width=50%} + +. . . + +* Réponse: ben non! + +# Utilisation quotidienne + +## Réseau social + +{width=40%} + +* Chaque sommet est un individu. +* Chaque trait une relation d'amitié. +* Miam, Miam, Facebook. + +# Utilisation quotidienne + +## Moteurs de recherche + +{width=40%} + +* Sommet est un site. +* Liens sortants; +* Liens entrants; +* Notion d'importance d'un site: combien de liens entrants, pondérés par l'importance du site. +* Miam, Miam, Google (PageRank). + +# Introduction + +## Définition, plus ou moins + +* Un graphe est un ensemble de sommets, reliés par des lignes ou des flèches. + + + +* Des sommets (numérotés 1 à 6); +* Connectés ou pas par des traits ou des flèches! + +# Généralités + +## Définitions + +* Un **graphe** $G(V, E)$ est constitué + * $V$: un ensemble de sommets; + * $E$: un ensemble d'arêtes. +* Une **arête** relie une **paire** de sommets de $V$. + +## Remarques + +* Il y a **au plus** une arête $E$ par paire de sommets de $V$. +* La **complexité** d'un algorithme dans un graphe se mesure en terme de $|E|$ et $|V|$, le nombre d'éléments de $E$ et $V$ respectivement. + +# Généralités + +## Notations + +* Une arête d'un graphe **non-orienté** est représentée par une paire **non-ordonnée** $(u,v)=(v,u)$, avec $u,v\in V$. +* Les arêtes ne sont pas orientées dans un graphe non-orienté (elles sont bi-directionnelles, peuvent être parcourues dans n'importe quel ordre). + +## Exemple + + +::: columns + +:::: column + + + + +:::: + +:::: column + +## Que valent $V$, $|V|$, $E$, et $|E|$? + +. . . + +\begin{align*} +V&=\{1, 2, 3, 4\},\\ +|V|&=4,\\ +E&=\{(1,2),(2,3),(2,4),(4,1)\},\\ +|E|&=4. +\end{align*} + +:::: + +::: + +# Généralités + +## Notations + +* Une arête d'un graphe **orienté** est représentée par une paire **ordonnée** $(u,v)\neq(v,u)$, avec $u,v\in V$. +* Les arêtes sont orientées dans un graphe orienté (étonnant non?). + +## Exemple + + +::: columns + +:::: column + + + + +:::: + +:::: column + +## Que valent $V$, $|V|$, $E$, et $|E|$? + +. . . + +\begin{align*} +V&=\{1, 2, 3, 4\},\\ +|V|&=4,\\ +E&=\{(1,2),(2,3),(2,4),(4,1),(4,2)\},\\ +|E|&=5. +\end{align*} + +:::: + +::: + +# Généralités + +## Définition + +* Le somme $v$ est **adjacent** au sommet $u$, si et seulement si $(u,v)\in E$; +* Si un graphe non-orienté contient une arête $(u,v)$, $v$ est adjacent à $u$ et $u$ et adjacent à $v$. + +## Exemple + +::: columns + +:::: column + +{width=80%} + +:::: + +:::: column + +{width=80%} + +:::: + +::: + +# Généralités + +## Définition + +* Un **graphe pondéré** ou **valué** est un graphe dont chaque arête a un + poids associé, habituellement donné par une fonction de pondération $w:E\rightarrow\mathbb{R}$. + +## Exemples + +{width=80%} + + +# Généralités + +## Définition + +* Dans un graphe $G(V,E)$, une **chaîne** reliant un sommet $u$ à un sommet $v$ est une suite d'arêtes entre les sommets, $w_0$, $w_1$, ..., $w_k$, telles que +$$ +(w_i, w_{i+1})\in E,\quad u=w_0,\quad v=w_k,\quad \mbox{pour }0\leq i< k, +$$ +avec $k$ la longueur de la chaîne (le nombre d'arêtes du chemin). + +## Exemples + +{width=80%} + +# Généralités + +## Définition + +* Une **chaîne élémentaire** est une chaîne dont tous les sommets sont distincts, sauf les extrémités qui peuvent être égales + +## Exemples + +{width=80%} + +# Généralités + +## Définition + +* Une **boucle** est une arête $(v,v)$ d'un sommet vers lui-même. + +## Exemples + +{width=40%} + +# Généralités + +## Définition + +* Un graphe non-orienté est dit **connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts. + +## Exemples + +\ + +::: columns + +:::: column + +{width=80%} + +:::: + +:::: column +{width=60%} + +:::: + +::: + +# Généralités + +## Définition + +* Un graphe orienté est dit **fortement connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts. + +## Exemples + +\ + +::: columns + +:::: column + +{width=60%} + +:::: + +:::: column + +{width=100%} + +:::: + +::: + +# Généralités + +## Définition + +* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\geq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes. +* Pour un graphe *orienté* on parle de **circuit**. +* Un graphe sans cycles est dit **acyclique**. + +## Exemples + +{width=100%} + +# Question de la mort + +* Qu'est-ce qu'un graphe connexe acyclique? + +. . . + +* Un arbre! + +# Représentations + +* La complexité des algorithmes sur les graphes s'expriment en fonction du nombre de sommets $V$, et du nombre d'arêtes $E$: + * Si $|E|\sim |V|^2$, on dit que le graphe est **dense**. + * Si $|E|\sim |V|$, on dit que le graphe est **peu dense**. +* Selon qu'on considère des graphes denses ou peu denses, différentes structure de données peuvent être envisagées. + +## Question + +* Comment peut-on représenter un graphe informatiquement? Des idées (réflexion de quelques minutes)? + +. . . + +* Matrice/liste d'adjacence. + +# Matrice d'adjacence + +* Soit le graphe $G(V,E)$, avec $V=\{1, 2, 3, ..., n\}$; +* On peut représenter un graphe par une **matrice d'adjacence**, $A$, de dimension $n\times n$ définie par +$$ +A_{ij}=\left\{ \begin{array}{ll} + 1 & \mbox{si } i,j\in E,\\ + 0 & \mbox{sinon}. + \end{array} \right. +$$ + + +::: columns + +:::: column + +## Exemple + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---4; + 2---5; + 4---5; + 5---3; +``` + +:::: + +:::: column + +\footnotesize + +## Quelle matrice d'adjacence? + +. . . + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 1 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 4 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 1 | 0 +``` + +:::: + +::: + +# Matrice d'adjacence + +## Remarques + +* Zéro sur la diagonale. +* La matrice d'un graphe non-orienté est symétrique + +$$ +A_{ij}=A_{ji}, \forall i,j\in[1,n] +$$. + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---4; + 2---5; + 4---5; + 5---3; +``` + +:::: + +:::: column + +\footnotesize + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 1 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 4 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 1 | 0 +``` + +:::: + +::: + +# Matrice d'adjacence + +* Pour un graphe orienté (digraphe) + +::: columns + +:::: column + +## Exemple + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 2-->1; + 1-->4; + 2-->5; + 5-->2; + 4-->5; + 5-->3; +``` + +:::: + +:::: column + +\footnotesize + +## Quelle matrice d'adjacence? + +. . . + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 0 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 0 +---||---|---|---|---|--- + 4 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 0 | 0 +``` + +:::: + +::: + +* La matrice d'adjacence n'est plus forcément symétrique +$$ +A_{ij}\neq A_{ji}. +$$ + +# Stockage + +* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe orienté? + +. . . + +* $\mathcal{O}(|V|^2)$. +* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe non-orienté? + +. . . + +* $\mathcal{O}(|V|-1)|V|/2$. + +# Considérations d'efficacité + +* Dans quel type de graphes la matrice d'adjacence est utile? + +. . . + +* Dans les graphes denses. +* Pourquoi? + +. . . + +* Dans les graphes peu denses, la matrice d'adjacence est essentiellement composée de `0`. + +## Remarque + +* Dans la majorité des cas, les grands graphes sont peu denses. +* Comment représenter un graphe autrement? + +# La liste d'adjacence (non-orienté) + +* Pour chaque sommet $v\in V$, stocker les sommets adjacents à $v$- +* Quelle structure de données pour la liste d'adjacence? + +. . . + +* Tableau de liste chaînée, vecteur (tableau dynamique), etc. + + +::: columns + +:::: column + +## Exemple + +{width=80%} + +:::: + +:::: column + + +## Quelle liste d'adjacence? + +. . . + + + + +:::: + +::: + +# La liste d'adjacence (orienté) + + +::: columns + +:::: column + +## Quelle liste d'adjacence pour... + +* Matrix (2min) + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 0-->1; + 0-->2; + 1-->2; + 3-->0; + 3-->1; + 3-->2; +``` + +:::: + +:::: column + +``` + + + + + + + + + + + +``` + + +:::: + +::: + +# Complexité + +## Stockage + +* Quelle espace est nécessaire pour stocker une liste d'adjacence (en fonction de $|E|$ et $|V|$)? + +. . . + +$$ +\mathcal{O}(|E|) +$$ + +* Pour les graphes *non-orientés*: $\mathcal{O}(2|E|)$. +* Pour les graphes *orientés*: $\mathcal{O}(|E|)$. + +## Définition + +* Le **degré** d'un sommet $v$, est le nombre d'arêtes incidentes du sommet (pour les graphes orientés on a un degré entrant ou sortant). +* Comment on retrouve le degré de chaque sommet avec la liste d'adjacence? + +. . . + +* C'est la longueur de la liste chaînée. + + +# Parcours + +* Beaucoup d'applications nécessitent de parcourir des graphes: + * Trouver un chemin d'un sommet à un autre; + * Trouver si le graphe est connexe; +* Il existe *deux* parcours principaux: + * en largeur (Breadth-First Search); + * en profondeur (Depth-First Search). +* Ces parcours créent *un arbre* au fil de l'exploration (si le graphe est non-connexe cela crée une *forêt*, un ensemble d'arbres). + +# Illustration: parcours en largeur + +{width=80%} + +# Exemple + +## Étape par étape (blanc non-visité) + +{width=50%} + +## Étape par étape (gris visité) + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape (vert à visiter) + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# En faisant ce parcours... + + +::: columns + +:::: column + +## Du parcours de l'arbre + +{width=100%} + +:::: + +:::: column + +## Quel arbre est créé par le parcours (2min)? + +. . . + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 0[x]-->1[w]; + 0-->2[t]; + 0-->3[y]; + 2-->9[u]; + 1-->4[s]; + 4-->5[r]; + 5-->6[v]; +``` + +:::: + +::: + +## Remarques + +* Le parcours dépend du point de départ dans le graphe. +* L'arbre sera différent en fonction du noeud de départ, et de l'ordre de parcours des voisins d'un noeud. + +# Le parcours en largeur + +## L'algorithme, idée générale (3min, matrix)? + +. . . + +```C +v = un sommet du graphe +i = 1 +pour sommet dans graphe et sommet non-visité + visiter(v, sommet, i) // marquer sommet à distance i visité + i += 1 +``` + +## Remarque + +* `i` est la distance de plus cours chemin entre `v` et les sommets en cours de visite. + + +# Le parcours en largeur + +## L'algorithme, pseudo-code (3min, matrix)? + +* Comment garder la trace de la distance? + +. . . + +* Utilisation d'une **file** + +. . . + +```C +initialiser(graphe) // tous sommets sont non-visités +file = visiter(sommet, vide) // sommet est un sommet du graphe au hasard +tant que !est_vide(file) + v = défiler(file) + file = visiter(v, file) +``` + +## Que fait visiter? + +``` +file visiter(sommet, file) + sommet = visité + pour w = chaque arête de sommet + si w != visité + file = enfiler(file, w) + retourne file +``` + +# Exercice (5min) + +## Appliquer l'algorithme sur le graphe + +{width=50%} + +* En partant de `v`, `s`, ou `u` (par colonne de classe). +* Bien mettre à chaque étape l'état de la file. + +# Complexité du parcours en largeur + +## Étape 1 + +* Extraire un sommet de la file; + +## Étape 2 + +* Traîter tous les sommets adjacents. + +## Quelle est la complexité? + +. . . + +* Étape 1: $\mathcal{O}(|V|)$, +* Étape 2: $\mathcal{O}(2|E|)$, +* Total: $\mathcal{O}(|V| + |2|E|)$. + +# Exercice + +* Établir la liste d'adjacence et appliquer l'algorithme de parcours en largeur au graphe + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---3; + 1---4; + 2---3; + 2---6; + 3---6; + 3---4; + 3---5; + 4---5; +``` + + +# Illustration: parcours en profondeur + +{width=80%} + +# Parcours en profondeur + +## Idée générale + +* Initialiser les sommets comme non-lus +* Visiter un sommet +* Pour chaque sommet visité, on visite un sommet adjacent s'il est pas encore visité récursivement. + +## Remarque + +* La récursivité est équivalent à l'utilisation d'une **pile**. + +# Parcours en profondeur + +## Pseudo-code (5min) + +. . . + +```C +initialiser(graphe) // tous sommets sont non-visités +pile = visiter(sommet, vide) // sommet est un sommet du graphe au hasard +tant que !est_vide(pile) + v = dépiler(pile) + pile = visiter(v, pile) +``` + +## Que fait visiter? + +. . . + +```C +pile visiter(sommet, pile) + sommet = visité + pour w = chaque arête de sommet + si w != visité + pile = empiler(pile, w) + retourne pile +``` + + +# Exercice + +* Établir la liste d'adjacence et appliquer l'algorithme de parcours en profondeur au graphe + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---3; + 1---4; + 2---3; + 2---6; + 3---6; + 3---4; + 3---5; + 4---5; +``` + +# Interprétation des parcours + +* Un graphe vu comme espace d'états (sommet: état, arête: action); + * Labyrinthe; + * Arbre des coups d'un jeu. + +. . . + +* BFS (Breadth-First) ou DFS (Depth-First) parcourent l'espace des états à la recherche du meilleur mouvement. + * Les deux parcourent *tout* l'espace; + * Mais si l'arbre est grand, l'espace est gigantesque! + +. . . + +* Quand on a un temps limité + * BFS explore beaucoup de coups dans un futur proche; + * DFS explore peu de coups dans un futur lointain. -- GitLab