Methode Du Plus Court Chemin
Methode Du Plus Court Chemin
Methode Du Plus Court Chemin
RAPPORT DE
PROJET
METHODE DU PLUS
COURT CHEMIN DANS
UN GRAPHE MODLIS
PAR UNE LISTE
DADJACENCE
Anne universitaire 2015/2016
Ralis par :
TABLE OF CONTENTS
Contents
Introduction _______________________________________________________________ 1
Les graphes ________________________________________________________________ 2
Les classes templates utilises ___________________________________________________ 6
Reprsentation de la liste dadjacence _____________________________________________ 8
Parcours en largeur __________________________________________________________11
Le code ___________________________________________________________________13
Introduction
Page 1
Les graphes
Page 2
Matrice dadjacence
Liste dadjacence
Page 3
1: 2 -> 5
2: 1 -> 3 -> 5
3: 2 -> 4
4: 3 -> 5 -> 6
5: 1 -> 2 -> 4
6: 4
Le nud 1 a dans sa liste dadjacence les nuds 2 et 5, le nud
2 a dans sa liste les nuds 1, 3 et 5 ainsi de suite.
Quelle reprsentation choisir entre les deux ?
Chacune de ces 2 reprsentations a des avantages et des
inconvnients. Par exemple, pour vrifier si 2 nuds sont
connects dans une reprsentation par liste dadjacence, on est
oblig de parcourir squentiellement G[i] pour y rechercher j
alors quavec une reprsentation par matrice dadjacence, il suffit
de vrifier si G[i][j] vaut 1, ce qui prend un temps constant.
Cependant, plus le graphe est grand, plus la reprsentation par
Page 4
Page 5
std::list<T,...>
La classe list fournit une structure gnrique de listes chanes
pouvant ventuellement contenir des doublons.
Complexit :
Page 6
std::vector<T,...>
La classe vector est proche du tableau du C. Tous les
lments contenus dans le vector sont adjacents en mmoire,
ce qui permet d'accder immdiatement n'importe quel
lment. L'avantage du vector compar au tableau du C est sa
facult se rallouer automatiquement en cas de besoin lors
d'un push_back ou d'un resize par exemple. Cependant une
case n'est accessible par l'oprateur que si elle a t alloue au
pralable (sinon une erreur de segmentation se dclenche).
Page 7
#include<iostream>
#include<list>
int main()
{
list<int> graph[MAX]; // On dclare un tableau de listes de
taille MAX pour qu'on puisse commencer l'indice 1 au lieu de 0
return 0;
}
Page 8
list<int> graph[MAX];
Page 9
return 0;
}
Pour ajouter un lment la liste dadjacence dun nud, il suffit
dappeler lune des fonctionspush_front() (insertion en tte de la
liste) ou push_back() (insertion en queue de la liste) de la STL.
Par exemple pour ajouter le nud 2 la liste dadjacence de 1,
on fera :
graph[1].push_front(2);
// ou alors
graph[1].push_back(2);
Page 10
Parcours en largeur
Le parcours en largeur dun graphe ou breadth first
search (en anglais) est un algorithme de parcours trs simple.
A partir dun nud origine, il passe par tous les arcs du graphe
pour dcouvrir les nuds accessibles depuis ce nud origine.
Donc, il permet partir dun nud de connatre tous les nuds
qui lui sont accessibles. Mais pas seulement, il calcule aussi la
distance entre ce nud et les nuds qui lui sont accessibles. Et
il permet aussi de construire le chemin qui relie ce nud origine
chacun des nuds qui lui sont accessibles. Le parcours en
largeur a une proprit trs intressante (peut-tre la plus
intressante), prenons un graphe G sur lequel on a fait un
parcours en largeur partir dun nud u; pour tout nud v
accessible depuis u, le chemin de u vers v dans G constitue un
plus court chemin de u vers v dans G. Ce qui veut donc dire que
le parcours en largeur calcule les plus courts chemins du nud
origine vers chacun des nuds qui lui sont accessibles.
Fonctionnement :
Lalgorithme utilise une file FIFO (premier entr, premier sorti)
pour parcourir le graphe. On insre dabord le nud origine src
dans la file. Tant que cette file nest pas vide, on rcupre son
1er lment, (notons le u), on parcourt la liste dadjacence de u;
chaque nud v rencontr, si le nud n a pas encore t
dcouvert, on le marque comme dcouvert, sinon on passe, on
indique ensuite que le prdcesseur ou parent de v dans le
graphe est u et on calcule la distance qui mne de src v en
ajoutant 1 la distance qui mne de src u.
Pour calculer les distances, on stocke en parallle un
tableau dist[N] (N, le nombre de noeuds du graphe), qui pour
chaque nud u stocke la distance menant de la source u. Au
Page 11
Page 12
Le code
Code :
#include<iostream>
#include<vector>
#include<list>
#include<queue>
using namespace std;
enum {WHITE, GREY, BLACK}; // Une numration pour les couleurs BLANC, GRIS
et NOIR
Page 13
/* Pour commencer */
for(int i = 1; i <= N; ++i)
{
color[i] = WHITE; // On colorie tous les noeuds en blanc
dist[i] = INF; // On affecte INF la distance de chaque noeud
parent[i] = NIL; // On affecte NIL au parent de chaque noeud
}
queue<int> q;
q.push(src); // On y insre notre source
while(!q.empty())
{
int u = q.front(); // on rcupre le noeud en tte de la queue
q.pop(); // On dfile la queue
Page 14
color[u] = BLACK;
}
}
Page 15
if(src == dest)
printf("%d", src);
else if(parent[dest] == NIL)
printf("Il n'y a pas de chemin de %d vers %d\n", src, dest);
else
{
print_path(src, parent[dest]);
printf(" %d", dest);
}
}
Exemple
Nous allons excuter un parcours en largeur partir du noeud 1
sur le graphe ci-dessous et afficher tous les plus courts chemins
menant de 1 chacun des autres noeuds.
Page 16
Voici le code
#include<iostream>
#include<vector>
#include<list>
#include<queue>
Page 17
const int N = 6;
const int MAX = N + 1;
vector<int> color(MAX);
vector<int> dist(MAX);
vector<int> parent(MAX);
/* Parcours en largeur */
void bfs(int src, list<int> graph[])
{
for(int i = 1; i <= N; ++i)
{
color[i] = WHITE;
dist[i] = INF;
parent[i] = NIL;
}
color[src] = GREY;
dist[src] = 0;
parent[src] = NIL;
Page 18
queue<int> q;
q.push(src);
while(!q.empty())
{
int u = q.front();
q.pop();
q.push(v);
}
}
color[u] = BLACK;
}
Page 19
int main()
{
int n = 0;
scanf("%d", &n);
list<int> graph[MAX];
Page 20
while(n--)
{
int u = 0, v = 0;
scanf("%d %d", &u, &v);
int src = 1;
bfs(src, graph); // On fait le parcours en largeur
return 0;
Page 21
Page 22