Vous êtes sur la page 1sur 84

Chapitre IV :

Chapitre IV : Algorithmique avancé et


programmation

www.hichamhatimi.com
I. Méthodes de tri
1- Définition

Un algorithme de tri est, en informatique


ou en mathématiques, un algorithme qui
permet d'organiser une collection d'objets
selon un ordre déterminé. Les objets à trier
font donc partie d'un ensemble muni d'une
relation d'ordre. Les ordres les plus utilisés
sont l’ordre numérique et l'ordre
lexicographique.
2
I. Méthodes de tri
2- Tri à bulles

Principe
Comparaison 2 à 2 des éléments adjacents et
échange s'ils ne sont pas ordonnés. Le
programme s'arrête lorsqu'on parcours la
liste sans faire d'échange Comme les bulles,
les plus grands éléments remontent en fin de
liste
3
I. Méthodes de tri
2- Tri à bulles
Exercice

Ecrire la fonction triBulles(ls) qui


permet de trier les éléments de la liste
ls en utilisant la méthode de tri à bulles

4
I. Méthodes de tri
2- Tri à bulles
Implémentation

def triBulles (ls):


echange= True #On suppose qu'il existe des permutation
while echange==True :
echange=False #On suppose pas de permut…
for i in range(0,len(ls)-1) :
if(ls[i]>ls[i+1]):
val=ls[i]
ls[i]=ls[i+1]
ls[i+1]=val
echange=True
5
I. Méthodes de tri
2- Tri à bulles
Exemple d'utilisation

T = [25,15,56,4,89,23,6]
print("Avant le tri : ",T)
triBulles(T)
print("Apres le tri :",T)

6
I. Méthodes de tri
3- Tri par sélection

Principe :
 Recherche du plus petit élément du tableau et
échange avec le premier élément
 Recherche du plus petit élément du tableau entre
les positions 1 et n-1 et échange avec le second
élément
 ...
 Recherche du plus petit élément entre les positions
n-2 et n-1 et échange avec l' élément en position n-
2
7
Exemple :
T =[ 28, 14, 16, 5, 11, 3, 22]
Etape 0 : [3, 14, 16, 5, 11, 28, 22]
Etape 1 : [3, 5, 16, 14, 11, 28, 22]
Etape 2: [3, 5, 11, 14, 16, 28, 22]
Etape 3: [3, 5, 11, 14, 16, 28, 22]
Etape 4: [3, 5, 11, 14, 16, 28, 22]
Etape 5: [3, 5, 11, 14, 16, 22, 28]

8
I. Méthodes de tri
3- Tri par sélection
Exercice

Ecrire la fonction triSelection(ls) qui


permet de trier les éléments de la liste ls
en utilisant la méthode de tri par
sélection.

9
I. Méthodes de tri
3- Tri par sélection
Implementation

def triSelection (ls):


for i in range(0,len(ls)-1) :
indice = i
for j in range(i+1,len(ls)) :
if ls[j] < ls[indice] :
indice = j
val=ls[indice]
ls[indice] = ls[i]
ls[i] = val

10
I. Méthodes de tri
3- Tri par sélection
Exemple d'utilisation

T = [25,15,56,4,89,23,6]
print("Avant le tri : ",T)
triSelection(T)
print("Apres le tri :",T)

11
I. Méthodes de tri
4- Tri par insertion

L'algorithme principal du tri par insertion est un


algorithme qui insère un élément dans une liste
d'éléments déjà triés (par exemple, par ordre
croissant).
Principe :
Pour chaque éléments d'indice i :
 La liste étant trié jusqu'à l'élément i-1,
 insérer l'élément i à sa place parmi les i
premiers éléments
12
I. Méthodes de tri
4- Tri par insertion
Exercice

Ecrire la fonction tri_insertion(T) qui


permet de trier les éléments de la liste T en
utilisant la méthode de tri par insertion.

13
I. Méthodes de tri
4- Tri par insertion
Implementation

def tri_insertion(T) :
n=len(T)
for i in range(1,n):
x=T[i]
j=i
while j>0 and T[j-1]>x :
T[j]=T[j-1]
j=j-1
T[j]=x

14
I. Méthodes de tri
4- Tri par insertion
Exemple d'utilisation

T = [25,15,56,4,89,23,6]
print("Avant le tri : ",T)
tri_insertion(T)
print("Apres le tri :",T)

15
I. Méthodes de tri
5- Tri rapide(QuickSort)

L’algorithme de tri rapide, "quick sort", est un


algorithme fondé sur la méthode de conception
diviser pour régner; Son principe consiste à séparer
l’ensemble des éléments en deux parties.
Pour effectuer la séparation, une valeur pivot est
choisie au hasard. Les valeurs sont réparties en
deux ensembles suivant qu’elles sont plus grandes
ou plus petites que le pivot. Ensuite, les deux
ensembles sont triés séparément, suivant la même
méthode.
16
I. Méthodes de tri
5- Tri rapide(QuickSort)

Exemple :
Soit la liste :
L = [ 4, 23, 3, 42, 2, 14, 45, 18, 38, 16 ]
Prenons comme pivot la dernière valeur
pivot = 16
Nous obtenons donc :
L1 = [4, 14, 3, 2]
L2 = [23, 45, 18, 38, 42]
A cette étape voici l'arrangement de L :
L =17L1 + pivot + L2 = [4, 14, 3, 2, 16, 23, 45, 18, 38, 42]
I. Méthodes de tri
5- Tri rapide(QuickSort)

En appliquant la même démarche au deux sous-


listes : L1 (pivot=2) et L2 (pivot=42)
[4, 14, 3, 2, 16, 23, 45, 18, 38, 42]
nous obtenons :
L11=[ ] liste vide
Pour L1 L12=[3, 4, 14]
L1=L11 + pivot + L12 = [2,3, 4, 14]
L21=[23, 38, 18]
Pour L2 L22=[45]
L2=L21 + pivot + L22 = [23, 38, 18, 42, 45]
18
I. Méthodes de tri
5- Tri rapide(QuickSort)
Fonction triRapide

def triRapide(T,premier,dernier) :
if premier < dernier :
indPivot=partitionner(T,premier,dernier)
triRapide(T,premier, indPivot-1)
triRapide(T, indPivot+1,dernier)

19
I. Méthodes de tri
5- Tri rapide(QuickSort)
Fonction partitionner

def partitionner(T,premier,dernier) :
j=premier
for i in range(premier,dernier) :
if T[i]<=T[dernier] :
T[i],T[j]=T[j],T[i]
j=j+1
T[dernier],T[j]=T[j],T[dernier]
return j

20
I. Méthodes de tri
5- Tri rapide(QuickSort)
Exemple d'utilisation

T = [25,15,56,4,89,23,13]
print("Avant le tri : ",T)
triRapide(T,0,6)
print("Apres le tri :",T)

21
I. Méthodes de tri
6- Tri par fusion

Le tri fusion est un algorithme de tri basé sur


la technique algorithmique diviser pour
régner. L'opération principale de l'algorithme
est la fusion, qui consiste à réunir deux listes
triées en une seule.

22
I. Méthodes de tri
6- Tri par fusion

Le principe de cet algorithme tend à adopter une


formulation récursive :
 On découpe les données à trier en deux parties
plus ou moins égales
 On trie les 2 sous-parties ainsi déterminées
 On fusionne les deux sous-parties pour
retrouver les données de départ

23
I. Méthodes de tri
6- Tri par fusion
Exemple

24
I. Méthodes de tri
6- Tri par fusion
Implémentation

L'implémentation de cet algorithme repose


essentiellement en 2 fonctions :
 Fusion :Permet de fusionner deux listes triées
de telle sorte que la liste résultante la soit aussi.
 triFusion : Une fonction récursive qui
assure le découpage de la liste et l'appel de la
fonction de fusion.

25
I. Méthodes de tri
6- Tri par fusion
Fonction fusion
def fusion(L1, L2):
res = []
ind1, ind2 = 0, 0
while ind1 < len(L1) and ind2 < len(L2):
if L1[ind1] <= L2[ind2]:
res = res + [L1[ind1]]
ind1 = ind1+1
else:
res = res + [L2[ind2]]
ind2 = ind2+1
if ind1!=len(L1):
res=res+L1[ind1:]
if ind2!=len(L2):
res=res+L2[ind2:]
26
return res
I. Méthodes de tri
6- Tri par fusion
Fonction triFusion

def triFusion(ls):
if len(ls) <= 1:
return ls
moitie = len(ls) // 2
L1= triFusion(ls[:moitie])
L2 = triFusion(ls[moitie:])
return fusion(L1,L2)

27
I. Méthodes de tri
6- Tri par fusion
Exemple d'utilisation

T = [25,15,56,4,89,23,6]
print("Avant le tri : ",T)
T=triFusion(T)
print("Apres le tri :",T)

28
II. Les arbres
1) Introduction

Un arbre est un ensemble d'éléments complexes relier


entre eux.
Nœud :
Value

left right

Nœud : Nœud :
Value Value

left right left right


NULL NULL NULL NULL

29
II. Les arbres
2) Terminologie
Tout d'abord, chaque élément d'un arbre se nomme un
nœud. Les nœuds sont reliés les uns aux autres par des
relations d'ordre ou de hiérarchie. Ainsi on dira qu'un
nœud possède un père, c'est à dire un nœud qui lui est
supérieur dans cette hiérarchie. Il possède
éventuellement un ou plusieurs fils.

Il existe un nœud qui n'a pas de père, c'est donc la


racine de l'arbre. Un nœud qui n'a pas de fils est appelé
une feuille. Parfois on appelle une feuille un nœud
externe tout autre nœud de l'arbre sera alors appelé un
nœud interne.
30
II. Les arbres
2) Terminologie
Degré d'un nœud : nombre de ses enfants
Profondeur d'un nœud : longueur du chemin entre la
racine et ce nœud
Hauteur d'un arbre : profondeur maximale de ses
nœuds
Hauteur d'un nœud : longueur maximale du chemin
entre ce nœud et une feuille
Niveau L dans un arbre : ensemble des nœuds de
profondeur L
Taille d'un arbre : nombre de ses nœuds

31
32
II. Les arbres
3) Types d'arbres
Il 'existe deux types d'arbres
 Les arbres binaires
 Les arbres n-aires

Arbre binaire Arbre n-aire

33
II. Les arbres
4) Parcourir un arbre en profondeur
Le parcours en profondeur permet d'explorer l'arbre en explorant
jusqu'au bout une branche pour passer à la suivante.
Les types de parcours en profondeur sont :
• Postfixe
tout Nœud est suivi des nœuds de son sous-arbre Gauche puis des
nœuds de son sous-arbre Droit
• Infixe
tout Nœud est précédé des nœuds de son sous-arbre Gauche et suivi
des nœuds de son sous-arbre Droit
• Suffixe
tout Nœud est précédé des nœuds de son sous-arbre Gauche et des
nœuds de son sous-arbre Droit

34
II. Les arbres
4) Parcourir un arbre en profondeur
• Postfixe : 1-2-3-4-5-6-7-8-9-
10
• Infixe : 4 – 3 -5 – 2-6-7-1-9-
8-10
• Suffixe :4-5-3-7-6-2-9-10-8-1

35
II. Les arbres
4) Parcourir un arbre en largeur
Parcourir un arbre en largeur consiste à visiter les nœuds
niveau par niveau depuis la racine.
Par exemple, le résultat pour cet arbre sera :
12 - 1 - 7- 91- 67- 61- 82- 32 - 45 - 50 - 40

36
II. Les arbres
5) Application sous Python
Pour construire un arbre binaire sous Python on
peut utiliser les listes ou autre structures de
données. Dans cette partie nous allons utilisé les
listes pour construire et gérer un arbre binaire. La
liste sera sous la forme suivante:
[donnée, sous_arbre_gauche, sous_arbre_droite]

Une feuille est la racine d’un arbre binaire dont la


sous arbre gauche et la sous-arbre droit sont égale
à None.
37
II. Les arbres
5) Application sous Python
Exemple :
Arb=[15, [7, [6, [None], [None]],[9, [None], [None]]], [20, [None], [25, [None],
[None]]]]

38
II. Les arbres
5) Application sous Python
Parcours en profondeur

Exemple :
def prefixe(arbre): def infixe(arbre):
if arbre!=[None]: if arbre!=[None]:
print(arbre[0]) infixe (arbre[1])
prefixe(arbre[1]) print(arbre[0])
prefixe(arbre[2]) infixe(arbre[2])

def suffixe(arbre):
if arbre!=[None]:
suffixe(arbre[1])
suffixe (arbre[2])
39
print(arbre[0])
II. Les arbres
5) Application sous Python
Parcours en profondeur
Exemple d'exécution :
Arb=[15, [7, [6, [None], [None]],[9, [None], [None]]],
[20, [None], [25, [None], [None]]]]
print("Affichage prefixe:")
prefixe(Arb)

40
II. Les arbres
5) Application sous Python
Parcourir un arbre en largeur
Pour programmer une telle opération, on peut utiliser les Files.
L'algorithme de la fonction sera :
affichageLargeur(a):
F : File #File FIFO
Enfiler(a,F) #enfiler la racine a dans la file F
tantque non vide(F):
n=Défiler(F)
Afficher(val(n))
si non vide(filsGauche(n)):
Enfiler(filsGauche(n),F)
si non vide(filsGauche(n)):
Enfiler(filsDroit(n),F)

41
II. Les arbres
5) Application sous Python
Parcourir un arbre en largeur
En python :
def parcoursLargeur(a):
F=[]
F.append(a)
while F!=[]:
n=F.pop(0) #Equiv : n=F[0] et del F[0]
print(n[0])
if n[1]!=[]:
F.append(n[1])
if n[2]!=[]:
F.append(n[2])
Arb=[15, [7, [6, [], []],[9, [], []]], [20, [], [25, [], []]]]
print("Affichage en largeur:")
parcoursLargeur(Arb)

42
II. Les arbres
6) Tri Maximier(tri par tas)
L'idée qui sous-tend cet algorithme consiste à voir le tableau comme un arbre
binaire. Le premier élément est la racine, le deuxième et le troisième sont les
deux descendants du premier élément, etc. Ainsi le ne élément a pour enfants
les éléments 2n et 2n+1. Si le tableau n'est pas de taille 2 1, les branches ne
se finissent pas toutes à la même profondeur. Dans l'algorithme, on cherche à
obtenir un tas, c'est-à-dire un arbre binaire vérifiant les propriétés suivantes
(les deux premières propriétés découlent de la manière dont on considère les
éléments du tableau) :
la différence maximale de profondeur entre deux feuilles est de 1 (toutes les
feuilles se trouvent sur la dernière ou sur l'avant-dernière ligne) ;
les feuilles de profondeur maximale sont « tassées » sur la gauche.
chaque nœud est de valeur supérieure (resp. inférieure) à celles de ses deux
fils, pour un tri ascendant (resp. descendant).
Il en découle que la racine du tas (le premier élément) contient la valeur
maximale (resp. minimale) de l'arbre. Le tri est fondé sur cette propriété

43
II. Les arbres
6) Tri Maximier(tri par tas)
def Tri_Maximier_par_tas(tab):
n = len(tab)
for debut in range(n- 1,-1,-1):
faire_tas(tab, debut)
for fin in range(n- 1,-1,-1):
tab[fin], tab[0] = tab[0], tab[fin]
faire_tas(tab[0:fin], 0)

44
II. Les arbres
6) Tri Maximier(tri par tas)
def faire_tas(tab, debut):
fin=len(tab)
pere = debut
while 2*pere + 1 < fin:
fils1 = 2*pere + 1
fils2 = 2*pere + 2
GF=fils1
if fils2 < fin and tab[fils1] < tab[fils2]:
GF=fils2
if tab[pere] < tab[GF]:
tab[pere], tab[GF] = tab[GF], tab[pere]
pere = GF
else:
return

45
III. Les graphes
1. Définitions
Graphe : Un graphe G est défini par G=(V,U), ou V est un
ensemble de sommets et U l’ensemble d'arcs(ou arêtes) ;
Un arc (ou arête) est un couple de sommets, donc, un
élément du produit cartésien VxV

46
III. Les graphes
1. Définitions

Graphe orienté et Graphe non orienté : Si les arêtes


ne sont pas orientées, on parle
d’un graphe non orienté. Dans le cas contraire on parle
d’un graphe orienté et les arêtes
sont appelées aussi les arcs.

47
III. Les graphes
1. Définitions

Graphe Pondéré : Un graphe pondéré est défini par le


triplet (V,U,C) où : V est l’ensemble des sommets, U est
l’ensemble des arrêtes (ou arcs), et C est la fonction de
coût de U.

48
III. Les graphes
1. Définitions

Graphe Connexe : Un graphe connexe est un graphe


dont tout couple de sommets peut être relie par une
chaine de longueur n>=1

A B
49
III. Les graphes
2. Terminologies

Ordre du Graphe : le nombre de sommet du Graphe

Graphe d'ordre 6

50
2. Terminologies

le degré (ou valence) d'un sommet d'un graphe est le


nombre de liens (arêtes ou arcs) reliant ce sommet.
Dans le cas d'un graphe orienté, on parle aussi du degré
entrant d'un sommet, c'est-à-dire le nombre d'arcs dirigés
vers le sommet, et du degré sortant de ce sommet, c'est-à-
dire le nombre d'arcs sortant. On a : le degré du sommet
est la somme du degré sortant et du degré entrant.

51
III. Les graphes
2. Terminologies

Adjacences:
Deux sommets sont adjacents lorsqu'ils sont joints par une
arête.
Deux arcs sont dits adjacents s'ils ont une extrémité en
commun.

52
III. Les graphes
2. Terminologies

Boucle : est un arc qui part d’un sommet vers le


même sommet

53
III. Les graphes
2. Terminologies

Chaîne : Une chaine de longueur n est une suite de n


arêtes qui relient un sommet i à un autre j ou à lui
même.

A – B – C – D – E est une chaîne de


longueur 4.

54
III. Les graphes
2. Terminologies
Cycle : Un cycle est une chaine qui permet de partir
d’un sommet et revenir a ce sommet en parcourant
une et une seule fois les autres sommets.

B – C – D – E – B est un cycle de longueur 4.

55
III. Les graphes
2. Terminologies
Distance entre deux sommets i et j est la longueur
de la chaine la plus courte qui les relie

La distance entre A et D est de 2

56
III. Les graphes
2. Terminologies
Chemin : c’est une chaine bien orientée
Un circuit ou cycle orienté : est un chemin dont l’origine et
l’extrémité sont confondus.

(1,4,2,3) est un chemin


57
(1,4,2,1) est un circuit
2. Terminologies
Chaine eulérienne: une chaine est dite eulérienne est une
chaine comportant exactement une fois toutes les arêtes du
graphe.
 Exemple :
B – A – D – B – C – D – E – A – C : Chaine eulérienne.

58
2. Terminologies
Cycle eulérien : si le sommet de départ d’une chaine eulérienne
est celui d’arrivé on parle de cycle eulérienne
Par exemple : Dans le graphe suivant, la chaîne A – B – C – D –
E – F – A est un cycle eulérien.

59
2. Terminologies

Graphe eulérien : Un graphe admettant une chaine


eulérienne est dit Graphe eulérien.
Cycle hamiltonien : c’est un cycle passant une seule fois
par tous les sommets d’un graphe et revenant au sommet
de départ.

60
III. Les graphes
3. Manipulation des graphes sous python
Un graphe peut être implémenté de différentes manières selon le
langage utilisé. En Python, on peut représenter un graphe à l’aide
d’un dictionnaire ou à l’aide d’une matrice d’adjacence:
Matrice d’adjacence
2 1 2 3 4 5
1 2
1 0 0 0 0 3
4
3 8 2 2 0 4 3 0
3 3
5 6 3 0 0 0 6 0
4
1 4 0 0 1 0 0
4
5 0 8 0 4 0
61
III. Les graphes
3. Manipulation des graphes sous python

 Exemple 2:

dictionnaire

62
Matrice d’adjacence
III. Les graphes
4. Algorithme de dijkstra
Il existe de nombreux algorithmes déterminant
un ou le plus court chemin dans un graphe
connexe pondéré. Par exemple: Warshall,
Floyd, Dijkstra, Branch and Bound, Bellman-
Ford
On se limitera à la recherche d'un plus court
chemin entre deux sommets du graphe pondéré
avec des poids positifs en utilisant la matrice
d’adjacence pour représenter le graphe.
63
III. Les graphes
4. Algorithme de dijkstra
On construit de proche en proche le chemin cherché en
choisissant à chaque itération de l'algorithme, un sommet si
du graphe parmi ceux qui n'ont pas encore été traités, tel que
la longueur connue provisoirement du plus court chemin
allant de E à si soit la plus court possible.

64
III. Les graphes
4. Algorithme de dijkstra
Algorithme :
Étape 1 : On affecte le poids 0 au sommet origine (E) et
on attribue provisoirement un poids ∞ aux autres
sommets.
Répéter les opérations suivantes tant que le sommet
de sortie (s) n'est pas affecté d'un poids définitif
Étape 2 : Parmi les sommets dont le poids n'est pas
définitivement fixé, choisir le sommet X de poids
minimal. Marquer définitivement ce sommet X

65
III. Les graphes
4. Algorithme de dijkstra
Étape 3 : Pour tous les sommets Y qui ne sont pas définitivement
marqués, adjacents au dernier sommet fixé X:
 Calculer la somme s du poids de X et du poids de l'arête reliant
X à Y.
 Si la somme s est inférieure au poids provisoirement affecté au
sommet Y, affecter provisoirement à Y le nouveau poids s et
indiquer le sommet X comme prédécesseur de Y pour se
souvenir de sa provenance.
Quand le sommet s est définitivement marqué Le plus court
chemin de E à S s'obtient en écrivant de gauche à droite le
parcours en partant de la fin S.

66
III. Les graphes
4. Algorithme de dijkstra

Soit le graphe suivant :


3

1 0
0 1 4
10
2
2
6 0
2
1
5
1 3
4
3

67
III. Les graphes
4. Algorithme de dijkstra

Matrice d'adjacence:

 Sommet de depart : 0
 d=[0, infini,infini, infini,infini,infini] # Liste des poids
 p=[0,-1,-1,-1,-1,-1] # Liste des prédécesseurs
 c=[0,1,2,3,4,5] # Sommet à marquer
68
III. Les graphes
4. Algorithme de dijkstra
x=0 (Sommet) x appartient c telque d[x] =min{d[j] telque j appartient c}
Pour tout sommet y de c:
d[y] = min(d[y],d[x]+G[x][y])
d[1]=min(d[1],d[x]+G[x][1]) = min(Infini,0+10) = 10
p[1] = x=0
d[2] = min(d[2],d[x]+G[x][2]) = min(Infini,0+3) = 3
p[2] = 0
d[3] = min(d[3],d[x]+G[x][3]) = min(Infini,0+Infini) = Infini
p[3] =-1(Aucune modification)
d[4] = min(d[4],d[x]+G[x][4]) = min(Infini,0+6) = 6
p[4] = 0
d[5] = min(d[5],d[x]+G[x][5]) = min(Infini,0+Infini) = Infini
p[5] = -1 (Aucune modification)
d=[0, 10, 3, infini, 6, Infini] # Liste des poids
p=[0,0,0,-1,0,-1] # Liste des prédécesseurs
c=[1,2,3,4,5] # Sommet à marquer

69
III. Les graphes
4. Algorithme de dijkstra
x=2 (Sommet)
d[1]=min(d[1],d[2]+G[2][1]) = min(10, 3+4) = 7
p[1] = 2
d[3] = min(d[3],d[2]+G[2][3]) = min(Infini,3+Infini) = Infini
p[3] = -1 (Aucune modification)
d[4] = min(d[4],d[2]+G[2][4]) = min(6,3+2) = 5
p[4] = 2
d[5] = min(d[5],d[2]+G[2][5]) = min(Infini,3+Infini) = Infini
p[5] = -1 (Aucune modification)
d=[0, 7, 3, infini, 5, Infini] # Liste des poids
p=[0,2,0,-1,2,-1] # Liste des prédécesseurs
c=[1,3,4,5] # Sommet à marquer
70
III. Les graphes
4. Algorithme de dijkstra
x=4 (Sommet)
d[1]=min(d[1],d[4]+G[4][1]) = min(7, 5+0) = 5
p[1] = 4
d[3] = min(d[3],d[4]+G[4][3]) = min(Infini,5+Infini) = Infini
p[3] = -1 (Aucune modification)
d[5] = min(d[5],d[4]+G[4][5]) = min(Infini,5+1) = 6
p[5] = 4
d=[0, 5, 3, infini, 5, 6] # Liste des poids
p=[0,4,0,-1,2,4] # Liste des prédécesseurs
c=[1,3,5] # Sommet à marquer

71
4. Algorithme de dijkstra

x=1
d[5] = min(d[5],d[1]+ G[1][5])=min(6,6)=6
d[3] = min(d[3],d[1]+ G[1][3])=min(infini,infini)=infini
d = [ 0, 5, 3, Infini, 5, 6 ]
p=[0, 4, 0, -1, 2, 4 ]
c = [ 3, 5 ]

72
4. Algorithme de dijkstra

x=5
d[3] = min(d[3],d[5]+ G[5][3])=min(infini,infini)=infini
d = [ 0, 5, 3, Infini, 5, 6 ]
p=[0, 4, 0, -1, 2, 4 ]
c=[3]

73
4. Algorithme de dijkstra
def dijkstra(G,s):
infini=G[0][0]
n=len(G)
D=[infini for i in range(n)]
D[s]=0
P=[-1 for i in range(n)]
P[s]=s
C=[i for i in range(n)]
while len(C)>0:
x=minD(D,C)
for k in C:
if D[x]+G[x][k]<D[k]:
D[k]=D[x]+G[x][k]
P[k]=x
C=supp(C,x)
return
74 P,D
III. Les graphes
4. Algorithme de dijkstra

def minD(LD,LC):
iminD=LC[0]
for i in LC:
if LD[i]<LD[iminD]:
iminD=i
return iminD
def supp(LC,v):
for i in range(len(LC)):
if LC[i] == v:
del LC[i]
return LC

75
III. Les graphes

 G=[[1000,…..]
 L=dijkstra(G,0)
 Print(L)
 Question : Ecrire une fonction chemin(G,s1,s2)
permettant d’afficher le chemin optimal entre
les sommets s1 et s2.Vous devez afficher aussi
le cout du chemin. Si le chemin n’existe pas
vous afficher « Le chemin n’existe pas »

76
III. Les graphes
5. Parcourir un graphe
a)Parcours en profondeur(DFS :Depht First Search)
L'algorithme sera :
1. Initialement tous les nœuds sont marqués " non visités".
2. Choisir un nœud v de départ et le marquer " visité".
3. Chaque nœud adjacent à v, non visité, est à son tour visité en
utilisant un traitement récursive.
4. Une fois tous les nœuds accessibles à partir de v ont été
visités, la recherche de v ( DFS(v) ) est complète.
5. Si certains nœuds du graphe restent "non visités",
sélectionner un comme nouveau nœud de départ et
répéter le processus jusqu'à ce que tous les nœuds soient
visités.

77
III. Les graphes
5. Parcourir un graphe
a)Parcours en profondeur
Code Python :
def DFSRecursif(G,s,etats):
etats[s]=1
print(s)
for x in voisinNonVisite(G,s,etats):
DFSRecursif(G,x,etats)
def voisinNonVisite(G,s,etats):
n=len(G[s])
infini = G[0][0]
L=[]
for i in range(n):
if G[s][i]!=infini and etats[i]==0:
L.append(i)
return L

78
III. Les graphes
5. Parcourir un graphe
a)Parcours en profondeur
def parcours(G):
etats=[0]*len(G)
for i in range(len(G)):
if etats[i]==0:
DFSRecursif(G,i,etats)
#Testes
G=[
[99,10,3,99, 6,99],
[ 0,99,99,99,99,1],
[99, 4,99,99, 2,99],
[ 99, 99,1,99,3,99],
[99, 0,99,99,99, 1],
[ 2, 99,99,99, 99,99]
]
print("Résultat du parcours en profondeur :")
parcours(G)

79
III. Les graphes
5. Parcourir un graphe
a)Parcours en profondeur
On peut aussi réaliser le parcours en profondeur en utilisant les Piles. Pour ce
faire on remplace la fonction DFSRecursif par la fonction suivante :
def parcoursDFSpile(G,s,etats):
pile=[s]
while pile!=[]:
noeud=pile.pop()
print(noeud)
etats[noeud]=1
voisin=voisinNonVisite(G,noeud,etats)
if voisin!=[]:
for x in voisin:
pile.append(x)

80
III. Les graphes
5. Parcourir un graphe
a)Parcours en profondeur
def parcours(G):
etats=[0]*len(G)
for i in range(len(G)):
if etats[i]==0:
parcoursDFSpile (G,i,etats)
#Testes
G=[
[99,10,3,99, 6,99],
[ 0,99,99,99,99,1],
[99, 4,99,99, 2,99],
[ 99, 99,1,99,3,99],
[99, 0,99,99,99, 1],
[ 2, 99,99,99, 99,99]
]
print("Résultat du parcours en profondeur :")
parcours(G)

81
III. Les graphes
5. Parcourir un graphe
b)Parcours en largeur(BFS Breadh First Search )
L'algorithme sera :
1) Dans le parcours en largeur, on utilise une file. On
enfile le sommet de départ
2) On visite les voisins de la tète de file. On les enfile.
3) On défile (c'est à dire : on supprime la tête de la file).
4) On recommence au point 2 (tant que la file n'est pas
vide)

82
III. Les graphes
5. Parcourir un graphe
b)Parcours en largeur
Code python :
def BFSFile(G,s,etats):
file=[s]
while file!=[]:
noeud=file.pop(0)
print(noeud,end=' ')
etats[noeud]=1
voisin=voisinNonVisite(G,noeud,etats)
if voisin!=[]:
for x in voisin:
file.append(x)

83
III. Les graphes
5. Parcourir un graphe
b)Parcours en largeur
def parcours(G):
etats=[0]*len(G)
for i in range(len(G)):
if etats[i]==0:
BFSFile (G,i,etats)
#Testes
G=[
[99,10,3,99, 6,99],
[ 0,99,99,99,99,1],
[99, 4,99,99, 2,99],
[ 99, 99,1,99,3,99],
[99, 0,99,99,99, 1],
[ 2, 99,99,99, 99,99]
]
print("Résultat du parcours en largeur:")
parcours(G)

84

Vous aimerez peut-être aussi