Vous êtes sur la page 1sur 6

Informatique Commune

1ère année

Introduction aux graphes

1 Graphes non-orientés
Un graphe non-orienté G est un couple (S, A) où S est un ensemble et A est un ensemble contenant
des paires d’éléments de S (c’est-à-dire des parties à deux éléments de S).
Les éléments de S sont appelés les sommets (ou nœuds) du graphe G et ceux de A les arêtes de G.
Derrière cette définition formelle, il faut garder à l’esprit l’idée suivante : un graphe, c’est un ensemble
de sommets dont certains sont reliés entre eux par des arêtes. On utilise d’ailleurs très souvent une repré-
sentation graphique de ces objets. Par exemple, le graphe G0 = (S, A) avec
S = {a, b, c, d, e, f, g, h} et A = {{a, b} , {a, d} , {b, c} , {c, d} , {c, e} , {d, e} , {f, g}} est représenté par :

b c e
f g
h
d
a

Il faut noter que comme les éléments de A sont des paires, il n’y a pas d’ordre privilégié dans leur écriture.
La paire {a, b} est la même que la paire {b, a}.
Deux sommets reliés par une arête sont dit voisins ou adjacents.
Dans le graphe G0 défini plus haut, a et b sont voisins mais d et b ne le sont pas. L’ensemble des voisins
de c est {b, d, e}.
On appelle degré d’un sommet le nombre de ses voisins. Pour un sommet s, on le note d(s).
On peut par exemple compléter le tableau suivant pour le graphe G0 :

Sommet a b c d e f g h

Degré

Dans le cadre de ce cours :

1. Il ne peut pas y avoir d’arête d’un sommet vers lui-même.


2. Il ne peut pas y avoir plusieurs arêtes reliant les deux même sommets.
3. La position géométrique des sommets n’a pas d’importance (toujours vrai).
Par exemple, les graphes suivants sont tous les mêmes :

4 4 3
4
3 2 2 2
3
5
0 1 0 1 0
1
5 5

2022 - 2023 1 Introduction aux graphes


M. Rogue A.
Informatique Commune
1ère année

2 Graphes orientés
Un graphe orienté G est un couple (S, A) où S est un ensemble et A est un ensemble contenant des
couples d’éléments de S.
Les éléments de S sont appelés les sommets (ou nœuds) du graphe G et ceux de A les arcs (parfois
arêtes) de G.
Si (a, b) est une arête de G, on dit que l’arête va de a à b ou encore que a est l’extrémité initiale (ou
sommet de départ) et b l’extrémité finale (ou sommet d’arrivée)
L’idée est presque la même que précédemment, à la différence que les arcs sont maintenant orientées :
ils ont tous un point de départ et un point d’arrivée. L’arc (a, b) n’est donc pas la même que l’arc (b, a).
Graphiquement, le changement s’opère en représentant les arc par des flèches, qui pointent vers le sommet
d’arrivée.
Par exemple, le graphe G1 = (S, A) avec S = {a, b, c, d, e, f, g, h, i, j} et
A = {(a, b), (b, a), (b, h), (h, d), (c, a), (d, e), (e, h), (c, f ), (f, g), (g, f ), (e, g), (i, j), (g, h)} est représenté
par :

c
f
b e

g
d h

a i j

Lorsqu’un arc (x, y) fait partie du graphe, on dit que x est un prédécesseur de y et que y est un
successeur de x Dans le graphe G1 , a et h sont les successeurs de b et a est l’unique prédécesseur de b.
On appelle degré sortant d’un sommet s le nombre de ses successeurs. C’est le nombre d’arcs qui
partent de ce sommet, on le note d− (s). Le degré entrant de s est le nombre de prédécesseurs de s
(c’est-à-dire le nombre d’arcs qui arrivent en s). On le note d+ (s).
Compléter le tableau suivant pour le graphe G1 :

Sommet a b c d e f g h i j

Degré entrant

Degré sortant

2022 - 2023 2 Introduction aux graphes


M. Rogue A.
Informatique Commune
1ère année

3 Implémentation des graphes en python


Pour travailler sur des graphes en python, il y a principalement deux manières de procéder.

3.1 Listes d’adjacences


La première consiste à faire la liste des voisins de chaque sommet pour un graphe non-orienté, ou la liste
des successeurs de chaque sommet pour un graphe orienté. Ces listes d’adjacence peuvent être stockées
soit dans une liste (on obtient alors une liste de liste), soit dans un dictionnaire.
Par exemple, le graphe de l’exemple suivant

2 3

0 5

1 4
graphe G2 :

peut être représenté en python avec une liste de listes


1 liste_listes_adjacence = [[1 ,2] ,[0 ,2 ,4] ,[0 ,1 ,3 ,4] ,[2] ,[1 ,2] ,[]]

ou avec un dictionnaire
1 dico_listes_adjacence =
↪ {0:[1 ,2] ,1:[0 ,2 ,4] ,2:[0 ,1 ,3 ,4] ,3:[2] ,4:[1 ,2] ,5:[]}

Ainsi, pour savoir si deux sommets sont voisins, il suffit d’effectuer un test d’appartenance à une liste
1 >>> 1 in liste_listes_adjacence [2] # Teste si 1 est un voisin de 2.
2 True
3 >>> 1 in dico_listes_adjacence [2] # Teste si 1 est un voisin de 2.
4 True

Cela fonctionne aussi pour un graphe orienté :

2 3

0 5

1 4
graphe G3 :

1 >>> liste_listes_adjacence = [[1 ,3] ,[2 ,3] ,[0] ,[1 ,2] ,[] ,[4]]
2 >>> dico_listes_adjacence = {0:[1 ,3] ,1:[2 ,3] ,2:[0] ,3:[1 ,2] ,4:[] ,5:[4]}
3 >>> 1 in dico_listes_adjacence [2] # Teste si 1 est un successeur de 2.
4 False

Avantages et inconvénients.
La représentation sous cette forme est très compacte, puisqu’il suffit de stocker chaque arête/arc en
mémoire. De plus, on peut facilement accéder aux voisins et au degré (ou degré sortant) d’un sommet.

2022 - 2023 3 Introduction aux graphes


M. Rogue A.
Informatique Commune
1ère année

1 def degre ( graphe : list , sommet : int ) -> int :


2 """ Entr é es : Un graphe sous forme de liste de listes d ’ adjacence , un
↪ entier qui est le num é ro d ’ un sommet du graphe .
3 Sortie : Le degr é du sommet ( degr é sortant dans le cas orient é ) .
4 """
5 return len ( graphe [ sommet ])

En revanche, l’accès au degré entrant (pour un graphe orienté) est nettement plus couteux en temps.
De plus, tester si une arête existe nécessite de parcourir toute la liste d’adjacence d’un sommet.

3.2 Matrices d’adjacences


On peut également représenter un graphe par une matrice d’adjacence. Pour cela, on construit une
matrice (une liste de listes en python) de taille n × n où n est le nombre de sommet du graphe. Le
coefficient de ligne i, colonne j vaut 1 si une arête/un arc va du sommet i vers le sommet j et vaut 0 sinon.
Si le graphe est non-orienté, la matrice associée est alors symétrique.
Exemples des matrices d’adjacence des deux graphes G2 et G3 précédemment explicités :

⎛0 1 1 0 0 0⎞ ⎛0 1 0 1 0 0⎞
⎜1 0 1 0 1 0⎟ ⎜0 0 1 1 0 0⎟
⎜ ⎟ ⎜ ⎟
⎜1 1 0 1 1 0⎟ ⎜1 0 0 0 0 0⎟
M2 = ⎜
⎜0
⎟, M3 = ⎜ ⎟
⎜ 0 1 0 0 0⎟

⎜0
⎜ 1 1 0 0 0⎟

⎜ ⎟ ⎜ ⎟
⎜0 1 1 0 0 0⎟ ⎜0 0 0 0 0 0⎟
⎝0 0 0 0 0 0⎠ ⎝0 0 0 0 1 0⎠
Soit en python :
1 M2 = [[0 ,1 ,1 ,0 ,0 ,0] ,[1 ,0 ,1 ,0 ,1 ,0] ,[1 ,1 ,0 ,1 ,1 ,0] ,[0 ,0 ,1 ,0 ,0 ,0] ,
↪ [0 ,1 ,1 ,0 ,0 ,0] ,[0 ,0 ,0 ,0 ,0 ,0]]
2 M3 = [[0 ,1 ,0 ,1 ,0 ,0] ,[0 ,0 ,1 ,1 ,0 ,0] ,[1 ,0 ,0 ,0 ,0 ,0] ,[0 ,1 ,1 ,0 ,0 ,0] ,
↪ [0 ,0 ,0 ,0 ,0 ,0] ,[0 ,0 ,0 ,0 ,1 ,0]]

Avantages et inconvénients.
Tester si une arête/un arc est présent se fait en temps constant. Trouver le degré entrant d’un sommet
dans un graphe orienté est plus rapide qu’avec les listes d’adjacence : Il suffit de parcourir la colonne
correspondant à ce sommet.
1 def degreEntrant ( graphe : list , sommet : int ) -> int :
2 """
3 Entr é es : Un graphe sous forme de matrice d ’ adjacence , un entier
4 qui est le num é ro d ’ un sommet du graphe .
5 Sortie : Le degr é du sommet ( son degr é entrant dans le cas orient é ) .
6 """
7 somme = 0
8 nb_sommets = len ( graphe )
9 for i in range ( nb_sommets ) :
10 if graphe [ i ][ sommet ] == 1:
11 somme +=1
12 return somme

En revanche, parcourir les voisins d’un sommet demande de parcourir toute une ligne de la matrice.
De plus, la matrice demande de stocker n2 coefficients pour un graphe à n sommets, ce qui peut être

2022 - 2023 4 Introduction aux graphes


M. Rogue A.
Informatique Commune
1ère année

problématique si l’on travaille sur un graphe avec beaucoup de sommets et (proportionnellement) peu
d’arêtes/arcs.

4 Déplacement dans un graphe


Un chemin dans un graphe est un enchaînement de déplacements d’un sommet à un autre selon des
arêtes/arcs présents dans le graphe (en respectant le sens de l’arc si le graphe est orienté).
Formellement, cela correspond aux définitions suivantes :
1. Si G = (S, A) est un graphe non-orienté, un chemin est une séquence de sommets s0 , s1 , s2 , . . . , sp−1 , sp
tel que pour tout i de 1 à p, {si−1 , si } est une arête de G.
2. Si G = (S, A) est un graphe orienté, un chemin est une séquence de sommets s0 , s1 , s2 , . . . , sp−1 , sp tel
que pour tout i de 1 à p, (si−1 , si ) est une arête de G.
Dans les deux cas, on dit que le chemin relie s0 et sp .

Dans ce graphe, le chemin 2 3


(3, 2, 1, 4) relie les sommets 3 et 6
4. 0 5

1 4

Dans celui-ci, le chemin 2 3


(3, 4, 1, 5, 1, 0) relie les sommets
3 et 0. 5 0 6

1 4

Un chemin est qualifié de cycle (ou circuit dans le cas orienté) si ses sommets de départ et d’arrivée
sont les mêmes et s’il ne passe que par des arêtes/arcs distincts. Dans le graphe non-orienté ci-dessus,
(0, 1, 2, 0) et (2, 4, 1, 0, 2) sont des cycles. Dans le graphe orienté, il y a par exemple les circuits (1, 5, 1) ou
encore (4, 1, 5, 2, 6, 3, 4).
Lorsqu’un graphe ne comporte aucun cycle, il est dit acyclique.
Une question naturelle se pose alors : Quels sommets est-il possible de relier ? C’est une question assez
simple lorsque l’on travaille sur un graphe de petite taille représenté graphiquement, mais on souhaite
disposer d’outils informatique pour automatiser cela et pouvoir le faire sur des graphes plus grands.
Un graphe non-orienté G est dit connexe si, pour deux sommets quelconques u et v de G, il existe un
chemin reliant u et v.

2 3
Exemple de graphe connexe.
0

1 4

Une technique classique pour savoir si un graphe est connexe consiste à « parcourir » le graphe en
partant d’un sommet, comme nous allons le voir dans la dernière section.

2022 - 2023 5 Introduction aux graphes


M. Rogue A.
Informatique Commune
1ère année

5 Un exemple de parcours de graphe : Détection de la connexité pour


les graphes non-orientés.
La fonction suivante détermine si un graphe est connexe. Elle est prévue pour un graphe donné sous
forme de liste de listes d’adjacence, mais peut s’adapter facilement en une version « matrice d’adjacence ».
1 def est_connexe ( graph : list ) -> bool :
2 """
3 Entr é e : un graphe non - orient é donn é par liste de listes d ’ adjacence .
4 Sortie : Un bool é en indiquant si le graphe est connexe . """
5 nb_sommets = len ( graph )
6 # Liste pour tenir à jour quels sommets ont déjà été atteints :
7 Sommets_vus = [ False for i in range ( nb_sommets ) ]
8 Sommets_vus [0] = True # Le point de dé part sera le sommet zé ro .
9 # On va stocker les sommets atteints , mais pas encore explor és , dans
10 # la liste Sommets_a_traiter
11 Sommets_a_traiter = [0]
12 # Compte le nombre de sommets atteints .
13 compte_vus = 1
14 # On parcourt le graphe tant qu ’il reste des sommets à traiter .
15 while len ( Sommets_a_traiter ) >0:
16 sommet = Sommets_a_traiter [0]
17 Sommets_a_traiter . remove ( sommet )
18 # Traiter un sommet : Rep é rer parmi ses voisins lesquels n ’ avaient
19 # pas encore été vus , et les ajouter dans la liste à traiter .
20 for voisin in graph [ sommet ]:
21 if not ( Sommets_vus [ voisin ]) :
22 Sommets_a_traiter . append ( voisin )
23 Sommets_vus [ voisin ] = True
24 compte_vus += 1
25 # On compare le nombre de sommets vus au nombre total pour savoir si
↪ on les a tous atteint .
26 return compte_vus == nb_sommets

Cette fonction n’est pas très efficace algorithmiquement car la gestion des sommets à traiter par une
liste est sous-optimale : les manipulations sur les listes impliquées font augmenter la complexité.
Nous verrons au prochain chapitre comment utiliser des structures de données plus adaptées au parcours
de graphe.

2022 - 2023 6 Introduction aux graphes


M. Rogue A.

Vous aimerez peut-être aussi