From ff338371e53dca10d32faf95f81619c4de605d78 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Mon, 13 May 2024 18:46:21 +0200 Subject: [PATCH] =?UTF-8?q?mise=20=C3=A0=20jour=202024?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- slides/cours_23.md | 1135 +------------------------------------- slides/cours_24.md | 1319 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1320 insertions(+), 1134 deletions(-) create mode 100644 slides/cours_24.md diff --git a/slides/cours_23.md b/slides/cours_23.md index a08b412..010781e 100644 --- a/slides/cours_23.md +++ b/slides/cours_23.md @@ -1,5 +1,5 @@ --- -title: "Les B-arbres et graphes" +title: "Les B-arbres" date: "2024-05-07" --- @@ -473,1136 +473,3 @@ page recherche(page, valeur) 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. diff --git a/slides/cours_24.md b/slides/cours_24.md new file mode 100644 index 0000000..cdfd861 --- /dev/null +++ b/slides/cours_24.md @@ -0,0 +1,1319 @@ +--- +title: "Les B-arbres et graphes" +date: "2024-05-14" +--- + +# Les B-arbres (rappel) + +## 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 (rappel) + +## Est-ce un B-arbre? + + + +. . . + +### Bien sûr! + +# Les B-arbres (rappel) + +## 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 (rappel) + +## L'insertion cas nœud pas plein, insertion `4`? + +{width=50%} + +. . . + +## Solution + +{width=50%} + +# Les B-arbres (rappel) + +## 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 (rappel) + +## L'insertion cas nœud plein, insertion `2`? + +{width=50%} + +. . . + +## Solution + +{width=50%} + +# Les B-arbres (rappel) + +## L'insertion cas nœud plein, promotion `3`? + +{width=50%} + +. . . + +## Solution + + + +# Les B-arbres (rappel) + +## 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 (rappel) + +## Pseudo-code structure de données + +. . . + +```C +struct page + entier ordre, nb + element tab[2*ordre + 2] +``` + +```C +struct element + entier clé + page pg +``` + +# Les B-arbres (rappel) + +\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 (rappel) + +\footnotesize + +## Les fonctions utilitaires + +```C +page nouvelle_page(ordre) // créer une page +``` +. . . + +```C +page nouvelle_page(ordre) + page = allouer(page) + page.ordre = ordre + page.nb = 0 + page.tab = allouer(2*ordre+2) + retourner page +``` + +# Les B-arbres (rappel) + +## Recherche de page + +```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 (nouveautés) + +## 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