Représentations de graphes

29 Apr 2019 29 Apr 2019 11604 vues ESSADDOUKI Mostafa 7 min de lecture
Complexité algorithmique
1 Introduction à l'analyse des algorithmes 2 Notations asymptotiques 3 Opérations élémentaires et modèles de coût 4 Complexité temporelle et spatiale 5 Méthode de comptage des pas 6 Méthode de comptage des pas pour les boucles
Diviser pour régner & algorithmes de tri
7 Rappel sur l'approche récursive 8 Diviser pour régner 9 la recherche dichotomique 10 Tri par fusion 11 Tri rapide 12 Analyse des fonctions récursives
Les arbres binaires
13 Introduction aux arbres binaires 14 Définitions récursives des arbres 15 Propriétés des arbres binaires 16 Types d'arbre binaire 17 Parcours en profondeur des arbres binaires 18 Parcours en largeur des arbres binaires 19 Exercices corrigés sur les arbres - TD 1 20 Exercices corrigés sur les arbres - TD 2 21 Exercices corrigés sur les arbres - TD 3 22 DS - Arbres binaires de recherche équilibrés (AVL) 23 DS - Codage de Huffman - Compression de données
Algorithmes gloutons
24 Introduction aux algorithmes gloutons 25 Problème de la sélection d'activités 26 Problème de séquencement des tâches 27 Problème du Sac à Dos fraction
Programmation dynamique
28 Introduction à la programmation dynamique 29 Le concept de sous-structure optimale 30 Le concept de sous-problèmes superposés 31 Méthodes de la programmation dynamique 32 Différence entre la programmation dynamique, l'approche diviser pour régner, et les algorithmes gloutons 33 Calculer les nombres de catalan en C++ et Python 34 Calculer le coefficient binomial 35 Le nombre de façons pour construire un mur de dimension 4*N 36 Défi de conversion de mots 37 Décomposition de phrases à partir d'un dictionnaire 38 La collection de pièces dans un labyrinthe 39 Nombre de façons de regrouper les étudiants 40 Compter tous les chemins possibles dans une grille MxN
Méta heuristique
41 Algorithmes heuristiques et métaheuristiques 42 Algorithme de Recuit simulé 43 Algorithme Colonies de fourmis
Théorie des graphes
44 Introduction et notions fondamentales 45 Chemins, cycles et connexité 46 Représentations des graphes 47 Parcours de graphes 48 Algorithme de Dijkstra 49 Algorithme A* 50 Algorithme de Bellman-Ford 51 Algorithme Floyd-Warshall 52 Coloration des graphes
Base de données et SQL
53 Introduction au langage SQL 54 Concepts de base de SGBDR 55 Syntaxes de différentes instructions SQL 56 Création et suppression d'une base de données 57 Opérateurs SQL 58 Les contraintes en SQL 59 Création et suppression des tables en SQL 60 Insertion et modifications des enregistrements 61 Extraction des données - SELECT 62 Filtrer les données - WHERE 63 Recherche de motifs - LIKE 64 Trier les données - ORDER BY 65 Les jointures en SQL - JOIN 66 Fonctions d'agrégation en SQL - SUM, COUNT, AVG, MIN et MAX 67 Organiser des données identiques en groupes - GROUP BY et HAVING 68 Les sous-requêtes en SQL 69 Les fonctions SQL de manipulation de date 70 DS - langage SQL 71 Exercices corrigés de langage SQL
Introduction à l'intelligence artificielle
Introduction à la théorie des jeux
Préparation aux concours
72 Réseau de distribution d'eau 73 Arbre d'expression arithmétique 74 Exploration d'une grotte souterraine

Représentations des graphes

En algorithmique, un graphe abstrait \(G = (S, A)\) doit être représenté concrètement en mémoire afin de permettre son traitement par des algorithmes (parcours, Dijkstra, etc.).

Le choix de la représentation est crucial :

  • il conditionne la complexité mémoire,
  • et la complexité temporelle des opérations fondamentales (parcours, test d'adjacence, etc.).

On distingue principalement trois représentations classiques.

Liste d'adjacence

C'est la structure privilégiée pour les graphes dits "creux" (peu d'arêtes par rapport au nombre de sommets).

Principe

On associe à chaque sommet \(u \in S\) une liste contenant ses voisins. \[ Adj[u] = \{ v \in S \mid (u, v) \in A \} \]

Remarque Dans une liste d'adjacence pondérée, chaque sommet \(u\) est associé à une liste de couples : \((v, w(u, v))\).

  Exemple

Graphe (a) - Non orienté

En observant le graphe, nous recensons les arêtes suivantes :

  • \(A\) est relié à : \(B, D, E\)
  • \(B\) est relié à : \(A, C, D, E\)
  • \(C\) est relié à : \(B, D\)
  • \(D\) est relié à : \(A, B, C\)
  • \(E\) est relié à : \(A, B\)
   
Liste d'adjacence - Graphe non orienté Python
adj_a = [
    [1, 3, 4],    # A est lié à B, D, E (index 0)
    [0, 2, 3, 4], # B est lié à A, C, D, E (index 1)
    [1, 3],       # C est lié à B, D (index 2)
    [0, 1, 2],    # D est lié à A, B, C (index 3)
    [0, 1]        # E est lié à A, B (index 4)
]
Graphe (b) - Orienté

En suivant les flèches :

  • A : Les flèches partent vers B, D, E.
  • B : Une seule flèche part vers E.
  • C : Une seule flèche part vers B.
  • D : Les flèches partent vers B, C.
  • E : Aucune flèche ne part de E.
   
Liste d'adjacence - Graphe orienté Python
adj_b = [
    [1, 3, 4], # A -> B, D, E
    [4],       # B -> E
    [1],       # C -> B
    [1, 2],    # D -> B, C
    []         # E n'a pas de flèche sortante
]

Utilisation de dictionnaire

L'utilisation d'un dictionnaire à la place d'une liste de listes est une variante très courante en Python, particulièrement utile lorsque les sommets ne sont pas numérotés de \(0\) à \(n-1\) (par exemple, si les sommets sont nommés "A", "B", etc.).

Au lieu d'utiliser l'indexation numérique d'un tableau, on utilise les identifiants des sommets comme clés du dictionnaire. Les valeurs associées sont les listes (ou ensembles) des voisins.

   
Liste d'adjacence avec dictionnaire Python
adj_a = {
    "A": ["B", "D", "E"],
    "B": ["A", "C", "D", "E"],
    "C": ["B", "D"],
    "D": ["A", "B", "C"],
    "E": ["A", "B"]
}

adj_b = {
    "A": ["B", "D", "E"],
    "B": ["E"],
    "C": ["B"],
    "D": ["B", "C"],
    "E": []
}

Matrice d'adjacence

Représentation privilégiée pour les graphes denses ou pour les preuves utilisant l'algèbre linéaire.

Principe

On utilise une matrice carrée \(A\) de taille \(|S| \times |S|\) telle que : \[ A[u][v] = \begin{cases} 1 & \text{si } (u,v) \in A \\ 0 & \text{sinon} \end{cases} \]

Remarque Pour le graphe non orienté, on remplit aussi \(A[v][u]\) car la relation est symétrique.

Dans une matrice d'adjacence pondérée :
  • l'entrée \(A[u][v]\) contient le poids de l'arête \(w(u,v)\),
  • l'absence d'arête est représentée par :
    • soit \(+\infty\),
    • soit une valeur sentinelle (ex. None),
    • jamais un poids valide.
Utiliser 0 pour signifier "pas d'arête" est dangereux si le graphe autorise des arêtes de poids nul.

  Exemple

Pour les graphes précédents, on obtient les matrices suivantes :

Graphe (a) - Non orienté

    A B C D E
A  [0,1,0,1,1]
B  [1,0,1,1,1]
C  [0,1,0,1,0]
D  [1,1,1,0,0]
E  [1,1,0,0,0]

Graphe (b) - Orienté

    A B C D E
A  [0,1,0,1,1]
B  [0,0,0,0,1]
C  [0,1,0,0,0]
D  [0,1,1,0,0]
E  [0,0,0,0,0]
   
Matrices d'adjacence Python
matrice_a = [
#    A  B  C  D  E   <- Sommet v
    [0, 1, 0, 1, 1], # A
    [1, 0, 1, 1, 1], # B
    [0, 1, 0, 1, 0], # C
    [1, 1, 1, 0, 0], # D
    [1, 1, 0, 0, 0]  # E
]

matrice_b = [
#    A  B  C  D  E   <- Sommet v
    [0, 1, 0, 1, 1], # A
    [0, 0, 0, 0, 1], # B
    [0, 1, 0, 0, 0], # C
    [0, 1, 1, 0, 0], # D
    [0, 0, 0, 0, 0]  # E
]

Matrice d'incidence

La matrice d'incidence est une représentation algébrique d'un graphe.

Contrairement à la matrice d'adjacence (centrée sur les relations sommet–sommet), elle met en évidence les relations sommet–arête.

Principe

Soit un graphe : \[ G = (S, A) \text{ avec } |S| = n,\ |A| = m \] La matrice d'incidence est une matrice : \[ M \in \mathbb{R}^{n \times m} \]

  • chaque ligne \(\Longleftrightarrow\) un sommet
  • chaque colonne \(\Longleftrightarrow\) une arête
Cas d'un graphe non orienté

Pour une arête \(e_k = \{u,v\}\) : \[ M[i][k] = \begin{cases} 1 & \text{si } i = u \text{ ou } i = v \\ 0 & \text{sinon} \end{cases} \]

Propriété Dans un graphe non orienté, la somme des coefficients d'une colonne \(= 2\) (car une arête relie deux sommets).

  Exemple pour le graphe (a)

    e1 e2 e3 e4 e5 e6 e7
    AB AD AE BC BD BE CD
A   [1, 1, 1, 0, 0, 0, 0]
B   [1, 0, 0, 1, 1, 1, 0]
C   [0, 0, 0, 1, 0, 0, 1]
D   [0, 1, 0, 0, 1, 0, 1]
E   [0, 0, 1, 0, 0, 1, 0]
   
Matrice d'incidence - Graphe non orienté Python
inc_a = [
#    e1 e2 e3 e4 e5 e6 e7
    [1, 1, 1, 0, 0, 0, 0], # A
    [1, 0, 0, 1, 1, 1, 0], # B
    [0, 0, 0, 1, 0, 0, 1], # C
    [0, 1, 0, 0, 1, 0, 1], # D
    [0, 0, 1, 0, 0, 1, 0]  # E
]
Cas d'un graphe orienté

Pour une arête orientée \(e_k = (u \rightarrow v)\) : \[ M[i][k] = \begin{cases} -1 & \text{si } i = u \quad (\text{sommet de départ}) \\ +1 & \text{si } i = v \quad (\text{sommet d'arrivée}) \\ 0 & \text{sinon} \end{cases} \]

PropriétéChaque colonne contient :
  • exactement un \(-1\)
  • exactement un \(+1\)
Donc la somme des coefficients d'une colonne \(= 0\).

  Exemple pour le graphe (b)

    e1 e2 e3 e4 e5 e6 e7
    A→B A→D A→E B→E C→B D→B D→C
A   [-1,-1,-1, 0, 0, 0, 0]
B   [ 1, 0, 0,-1, 1, 1, 0]
C   [ 0, 0, 0, 0,-1, 0, 1]
D   [ 0, 1, 0, 0, 0,-1,-1]
E   [ 0, 0, 1, 1, 0, 0, 0]
   
Matrice d'incidence - Graphe orienté Python
inc_b = [
#    a1  a2  a3  a4  a5  a6  a7
    [-1, -1, -1,  0,  0,  0,  0], # A
    [ 1,  0,  0, -1,  1,  1,  0], # B
    [ 0,  0,  0,  0, -1,  0,  1], # C
    [ 0,  1,  0,  0,  0, -1, -1], # D
    [ 0,  0,  1,  1,  0,  0,  0]  # E
]

Tableau comparatif des représentations

CritèreListe d'adjacenceMatrice d'adjacenceMatrice d'incidence
Mémoire\(O(|S| + |A|)\)\(O(|S|^2)\)\(O(|S| \times |A|)\)
Test d'adjacence \((u,v)\)\(O(\deg(u))\)\(O(1)\)\(O(|A|)\)
Parcours des voisins de \(u\)\(O(\deg(u))\)\(O(|S|)\)\(O(|A|)\)
Ajout d'une arête\(O(1)\)\(O(1)\)\(O(1)\) (ajout de colonne)
Suppression d'une arête\(O(\deg(u))\)\(O(1)\)\(O(1)\) (suppression de colonne)
Type de graphe idéalGraphes creuxGraphes densesApplications algébriques

Sortie
// La sortie apparaîtra ici…
Prêt · Ctrl+Entrée pour exécuter

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.