Devoir informatique pour l`unité d`enseignement :

publicité
Devoir informatique pour l’unité d’enseignement :
Traité par :
GUNES Aysel (Numéro étudiant : 10200610)
RAMOS Pierre (Numéro étudiant: 10002201)
Etudiants en Licence informatique troisième année
Professeurs d’informatique en Théorie des Graphes :
Cours magistraux : M LETOCART Lucas
Travaux dirigés : Mme TOULOUSE Sophie
(28/02/2005)
Sommaire
Introduction
I/ Présentation des algorithmes
1) Algorithme DFS
2) Algorithme de Kosaraju-Sharir
II/ Implémentation et commentaires du programme
III/ Résultats théoriques
1)
2)
3)
4)
Conclusion
Résultat théorique sur un graphe à 4 nœuds
Résultat théorique sur un graphe à 6 nœuds
Résultat théorique sur un graphe à 8 nœuds
Résultat théorique sur un graphe à 10 nœuds
Introduction
Dans le cadre de notre cursus en informatique, et plus précisément dans l’unité d’enseignement
Théorie des Graphes, nous considérons le problème de la recherche des composantes fortement connexes
d’un graphe orienté. Pour résoudre ce problème, nous allons utiliser l’algorithme de Kosaraju-Sharir vu
en cours et en travaux dirigés.
Ainsi, nous programmerons d’une part l’algorithme DFS (Deep First Search) et d’autre part,
l’algorithme de Kosaraju-Sharir. Le langage utilisé sera le langage C. Aussi, nous effectuerons une
analyse de complexité de l’implémentation faite.
Par conséquent, dans une première partie, nous présenterons les algorithmes DFS et KosarajuSharir. Dans une deuxième partie nous donnerons l’implémentation du programme. Et, dans une
dernière partie, nous donnerons les résultats théoriques obtenus sur quatre graphes différents.
I/ Présentation des algorithmes
Dans cette parie, nous présenterons les algorithmes DFS (Direct First Search) et Kosaraju-Sharir.
1) Algorithme DFS
Détermination des composantes fortement connexes.
G = (X, U)
Voici ci-dessous l’algorithme DFS (Deep First Search) tel que donné en cours.
Explication des notations :
G
: le graphe
k, f
: des entiers
i
: le sommet traité
n(i)
: le nombre de successeurs du sommet i
d(i)
: le degré du sommet i
num(i)
: la numérotation du sommet i
prefixe(i)
: la numérotation préfixe du sommet i
explore(G, i) : appel à la procédure explore prenant en paramètre le graphe G et le
sommet i
DFS (graphe G)
k  0
f  1
Pour i = 0 à n Faire n(i)  d(i)
Pour i = 0 à n Faire num(i)  0
Pour i = 0 à n Faire
Si num(i) = 0 Alors
k  k +1
num(i)  k
prefixe(i)  k
explore(G, i)
FinSi
FinPour
FinDFS
Voici ci-dessous l’algorithme de la procéure explore tel que donné en cours.
Explication des notations :
G
: le graphe
i
: le sommet traité
j
: représente le n(i)ème sommet successeur de i
k, f
: des entiers
n(i)
: le nombre de successeurs du sommet i
num(i)
: la numérotation du sommet i
prefixe(i)
: la numérotation préfixe du sommet i
suffixe(i)
: la numérotation suffixe du sommet i
explore(G, i) : appel à la procédure explore prenant en paramètre le graphe G et le
sommet i
Procédure explore(graphe G, sommet i)
Tantque n(i) > 0 Faire
Sélectionner j le n(i)ème successeur de i
n(i)  n(i) – 1
Si num(i) = 0 Alors
k  k + 1
num(j)  k
prefixe(j)  k
explore(G, j)
FinSi
FinTantque
suffixe(i)  f
f  f + 1
Finexplore
2) Algorithme de Kosaraju-Sharir
Détermination des composantes fortement connexes.
G = (X, U)
1)
2)
3)
Appilication de DFS(G) en numérotant les sommets dans l’ordre suffixe
Construction du graphe G’ = (X, U’) obtenu en inversant le sens des arcs de G.
Application de DFS(G’) en démarrant par le sommet de plus grand numéro suffixe et
itération du processus à partir du sommet non marqué de plus grand numéro suffixe.
II/ Implémentation et commentaires du
programme
Les commentaires sont faits avant chaque petite partie de code.
/* Declaration des bibliotheques */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* Definition des constantes */
#define TRUE 0
#define FALSE 1
/* Definition de structures de donnees */
/* valeur: la valeur du noeud
nbPred: le nombre de predecesseurs de ce noeud
nbSucc: le nombre de successeurs de ce noeud
successeurs: double pointeur sur cette structure de donnees
qui va representer l'ensemble des successeurs
de ce noeud
predecesseurs: double pointeur sur cette structure de donnees
qui va representer l'ensemble des predecesseurs
de ce neoud
nbSuccTemp: le nombre de successeurs de ce neoud (il est defini
comme temporaire dans la mesure où ce sera ce champ
qui sera modifie lors du parcours DFS et non le
champ nbSucc
numerotation: la numerotation de ce noeud
prefixe: la numerotation prefixe de ce noeud
suffixe: la numerotation suffixe de ce noeud
*/
typedef struct NoeudGraphe_{
int valeur;
int nbPred;
int nbSucc;
struct NoeudGraphe_** successeurs;
struct NoeudGraphe_** predecesseurs;
// les champs suivants ne sont utilises que dans
// le cadre d'un parcours DFS
int nbSuccTemp;
int numerotation;
int prefixe;
int suffixe;
}NoeudGraphe;
/* noeuds: pointeur sur la structure de donnees precedente
NoeudGraphe
nbnoeuds: le nombre de noeuds du graphe
*/
typedef struct{
NoeudGraphe* noeuds;
int nbNoeuds;
}Graphe;
/* Procedure permettant d'initialiser un nouveau noeud a partir des
valeurs envoyees en parametre; les champs utilises pour le
deroulement de l'algorithme DFS sont initialises a 0
*/
void nouveauNoeud(int valeur,int nbPred,int nbSucc,
NoeudGraphe** predecesseurs,
NoeudGraphe** successeurs,
int numerotation,NoeudGraphe* nouveauNoeud){
int i;
nouveauNoeud->valeur=valeur;
nouveauNoeud->nbPred=nbPred;
nouveauNoeud->nbSucc=nbSucc;
nouveauNoeud->nbSuccTemp=0;
nouveauNoeud->numerotation=numerotation;
nouveauNoeud->prefixe=0;
nouveauNoeud->suffixe=0;
nouveauNoeud->predecesseurs=
(NoeudGraphe**)malloc(nbPred*sizeof(NoeudGraphe*));
nouveauNoeud->successeurs=
(NoeudGraphe**)malloc(nbSucc*sizeof(NoeudGraphe*));
for(i=0;i<nbPred;i=i+1){
nouveauNoeud->predecesseurs[i]=predecesseurs[i];
}
for(i=0;i<nbSucc;i=i+1){
nouveauNoeud->successeurs[i]=successeurs[i];
}
}
/* Procedure explore qui sera utilisee pour le deroulement de
l'algorithme DFS prenant en argument un graphe, un noeud
de ce graphe et deux entiers
*/
int explore(NoeudGraphe *i,int k,int* f){
int renvoi=1;
while(i->nbSuccTemp>0){
i->nbSuccTemp=i->nbSuccTemp-1;
if(i->successeurs[i->nbSuccTemp]->numerotation==0){
k=k+1;
i->successeurs[i->nbSuccTemp]->numerotation=k;
i->successeurs[i->nbSuccTemp]->prefixe=k;
renvoi=1+explore(i->successeurs[i->nbSuccTemp],k,f);
}
}
i->suffixe=*f;
*f=(*f)+1;
return(renvoi);
}
/* Procedure implementant l'algorithme DFS qui sera utilise pour
le deroulement de l'algorithme Kosaraju-Sharir prenant en
argument un pointeur sur Graphe
*/
int dfs(Graphe* graphe){
int i,j,k,f;
int renvoi;
k=0;
f=1;
for(i=0;i<graphe->nbNoeuds;i=i+1){
graphe->noeuds[i].nbSuccTemp=graphe->noeuds[i].nbSucc;
graphe->noeuds[i].numerotation=0;
}
renvoi=graphe->nbNoeuds;
for(j=0;j<graphe->nbNoeuds;j=j+1){
if(graphe->noeuds[j].numerotation==0){
k=k+1;
graphe->noeuds[j].numerotation=k;
graphe->noeuds[j].prefixe=k;
renvoi=renvoi+explore(&(graphe->noeuds[j]),k,&f);
}
}
return(renvoi);
}
/* procedure implementant l'algorithme de Kosaraju-Sharir prenant
en argument deux pointeurs sur Graphe
*/
int kosarajuSharir(Graphe* graphe){
int i,j,nbSufMax,numSufMax,nbNumMax,numNumMax;
int* marquage;
int renvoi;
//graphe2 est un Graphe temporaire permettant de faire les tris
Graphe graphe2;
renvoi=dfs(graphe);
// On genere un 2ieme graphe, dont les noeuds sont tries
// dans l'ordre de leur notation suffixe
graphe2.nbNoeuds=graphe->nbNoeuds;
graphe2.noeuds=(NoeudGraphe*)malloc(graphe->
nbNoeuds*sizeof(NoeudGraphe*));
marquage=(int*)malloc(graphe->nbNoeuds*sizeof(int));
for(i=0;i<graphe->nbNoeuds;i=i+1){
marquage[i]=FALSE;
}
for(i=0;i<graphe->nbNoeuds;i=i+1){
numSufMax=-1;
for(j=0;j<graphe->nbNoeuds;j=j+1){
if(graphe->noeuds[j].suffixe>numSufMax){
if(marquage[j]==FALSE){
numSufMax=graphe->noeuds[j].suffixe;
nbSufMax=j;
}
}
}
marquage[nbSufMax]=TRUE;
nouveauNoeud(graphe->noeuds[nbSufMax].valeur,graphe->
noeuds[nbSufMax].nbSucc,graphe->
noeuds[nbSufMax].nbPred,graphe->
noeuds[nbSufMax].successeurs,graphe->
noeuds[nbSufMax].predecesseurs,graphe->
noeuds[nbSufMax].numerotation,&(graphe2.noeuds[i]));
}
renvoi=renvoi+graphe->nbNoeuds*3;
for(i=0;i<graphe->nbNoeuds;i=i+1){
nouveauNoeud(graphe2.noeuds[i].valeur,graphe2.noeuds[i].nbPred,
graphe2.noeuds[i].nbSucc,graphe2.noeuds[i].predecesseurs,
graphe2.noeuds[i].successeurs,graphe2.noeuds[i].numerotation,
&(graphe->noeuds[i]));
}
// On applique l'algorithme DFS au 2 ieme graphe genere
renvoi=renvoi+dfs(graphe);
// On trie les noeuds du 2 ieme graphe selon leur notation
// prefixe, ce qui les classe selon leur composante connexe
for(i=0;i<graphe->nbNoeuds;i=i+1){
marquage[i]=FALSE;
}
nbNumMax=0;
for(i=0;i<graphe->nbNoeuds;i=i+1){
numNumMax=graphe->nbNoeuds+1;
for(j=0;j<graphe->nbNoeuds;j=j+1){
if(graphe->noeuds[j].numerotation<numNumMax){
if(marquage[j]==FALSE){
numNumMax=graphe->noeuds[j].numerotation;
nbNumMax=j;
}
}
}
marquage[nbNumMax]=TRUE;
nouveauNoeud(graphe->noeuds[nbNumMax].valeur,graphe->
noeuds[nbNumMax].nbPred,graphe->
noeuds[nbNumMax].nbSucc,graphe->
noeuds[nbNumMax].predecesseurs,graphe->
noeuds[nbNumMax].successeurs,graphe->
noeuds[nbNumMax].numerotation,&(graphe2.noeuds[i]));
}
for(i=0;i<graphe->nbNoeuds;i=i+1){
nouveauNoeud(graphe2.noeuds[i].valeur,graphe2.noeuds[i].nbPred,
graphe2.noeuds[i].nbSucc,graphe2.noeuds[i].predecesseurs,
graphe2.noeuds[i].successeurs,graphe2.noeuds[i].numerotation,
&(graphe->noeuds[i]));
}
renvoi=renvoi+graphe2.nbNoeuds*3;
return(renvoi);
}
/* Procedure permettant d'initialiser un graphe a 10 noeuds,
ce graphe forme un circuit, il sera appele lors des tests
*/
void graphe10noeuds(Graphe* graphe) {
int i;
NoeudGraphe** tabPred;
NoeudGraphe** tabSucc;
graphe->nbNoeuds=10;
graphe->noeuds=(NoeudGraphe*)malloc(graphe->
nbNoeuds*sizeof(NoeudGraphe));
for(i=1;i<11;i=i+1){
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[((i-1)%10)];
tabSucc[0]=&graphe->noeuds[((i+1)%10)];
nouveauNoeud(i%10,1,1,tabPred,tabSucc,0,&(graphe->
noeuds[i%10]));
free(tabPred);
free(tabSucc);
}
}
/* Procedure permettant d'initialiser un graphe a 6 noeuds */
void graphe4noeuds(Graphe* graphe) {
NoeudGraphe** tabPred;
NoeudGraphe** tabSucc;
graphe->nbNoeuds=4;
graphe->noeuds=(NoeudGraphe*)malloc(graphe->
nbNoeuds*sizeof(NoeudGraphe));
// Noeud: 1
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[3];
tabSucc[0]=&graphe->noeuds[1];
tabSucc[1]=&graphe->noeuds[2];
nouveauNoeud(0,1,2,tabPred,tabSucc,0,&graphe->noeuds[0]);
free(tabPred);
free(tabSucc);
// Noeud: 2
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[0];
tabSucc[0]=&graphe->noeuds[3];
nouveauNoeud(1,1,1,tabPred,tabSucc,0,&graphe->noeuds[1]);
free(tabPred);
free(tabSucc);
// Noeud: 3
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[0];
tabSucc[0]=&graphe->noeuds[3];
nouveauNoeud(2,1,1,tabPred,tabSucc,0,&graphe->noeuds[2]);
free(tabPred);
free(tabSucc);
// Noeud: 4
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[1];
tabPred[1]=&graphe->noeuds[2];
tabSucc[0]=&graphe->noeuds[0];
nouveauNoeud(3,2,1,tabPred,tabSucc,0,&graphe->noeuds[3]);
free(tabPred);
free(tabSucc);
}
/* Procedure permettant d'initialiser un graphe a 6 noeuds */
void graphe6noeuds(Graphe* graphe) {
NoeudGraphe** tabPred;
NoeudGraphe** tabSucc;
graphe->nbNoeuds=6;
graphe->noeuds=(NoeudGraphe*)malloc(graphe->
nbNoeuds*sizeof(NoeudGraphe));
// Noeud: 1
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[2];
tabSucc[0]=&graphe->noeuds[1];
nouveauNoeud(0,1,1,tabPred,tabSucc,0,&graphe->noeuds[0]);
free(tabPred);
free(tabSucc);
// Noeud: 2
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[0];
tabPred[1]=&graphe->noeuds[5];
tabSucc[0]=&graphe->noeuds[2];
nouveauNoeud(1,2,1,tabPred,tabSucc,0,&graphe->noeuds[1]);
free(tabPred);
free(tabSucc);
// Noeud: 3
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[1];
tabPred[1]=&graphe->noeuds[4];
tabSucc[0]=&graphe->noeuds[0];
tabSucc[1]=&graphe->noeuds[3];
nouveauNoeud(2,2,2,tabPred,tabSucc,0,&graphe->noeuds[2]);
free(tabPred);
free(tabSucc);
// Noeud: 4
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[2];
tabPred[1]=&graphe->noeuds[4];
tabSucc[0]=&graphe->noeuds[5];
nouveauNoeud(3,2,1,tabPred,tabSucc,0,&graphe->noeuds[3]);
free(tabPred);
free(tabSucc);
// Noeud: 5
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[5];
tabSucc[0]=&graphe->noeuds[2];
tabSucc[1]=&graphe->noeuds[3];
nouveauNoeud(4,1,2,tabPred,tabSucc,0,&graphe->noeuds[4]);
free(tabPred);
free(tabSucc);
// Noeud: 6
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[3];
tabSucc[0]=&graphe->noeuds[1];
tabSucc[1]=&graphe->noeuds[4];
nouveauNoeud(5,1,2,tabPred,tabSucc,0,&graphe->noeuds[5]);
free(tabPred);
free(tabSucc);
}
/* Procedure permettant d'initialiser un graphe a 8 noeuds */
void graphe8noeuds(Graphe* graphe) {
NoeudGraphe** tabPred;
NoeudGraphe** tabSucc;
graphe->nbNoeuds=8;
graphe->noeuds=(NoeudGraphe*)malloc(graphe->
nbNoeuds*sizeof(NoeudGraphe));
// Noeud: 1
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[7];
tabSucc[0]=&graphe->noeuds[3];
nouveauNoeud(0,1,1,tabPred,tabSucc,0,&graphe->noeuds[0]);
free(tabPred);
free(tabSucc);
// Noeud: 2
tabPred=(NoeudGraphe**)malloc(1*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[3];
tabSucc[0]=&graphe->noeuds[2];
tabSucc[1]=&graphe->noeuds[4];
nouveauNoeud(1,1,2,tabPred,tabSucc,0,&graphe->noeuds[1]);
free(tabPred);
free(tabSucc);
// Noeud: 3
tabPred=(NoeudGraphe**)malloc(3*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[1];
tabPred[1]=&graphe->noeuds[4];
tabPred[2]=&graphe->noeuds[7];
tabSucc[0]=&graphe->noeuds[3];
tabSucc[1]=&graphe->noeuds[7];
nouveauNoeud(2,3,2,tabPred,tabSucc,0,&graphe->noeuds[2]);
free(tabPred);
free(tabSucc);
// Noeud: 4
tabPred=(NoeudGraphe**)malloc(3*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[0];
tabPred[1]=&graphe->noeuds[2];
tabPred[2]=&graphe->noeuds[3];
tabSucc[0]=&graphe->noeuds[5];
tabSucc[1]=&graphe->noeuds[1];
nouveauNoeud(3,3,2,tabPred,tabSucc,0,&graphe->noeuds[3]);
free(tabPred);
free(tabSucc);
// Noeud: 5
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[1];
tabPred[1]=&graphe->noeuds[5];
tabSucc[0]=&graphe->noeuds[2];
tabSucc[1]=&graphe->noeuds[6];
nouveauNoeud(4,2,2,tabPred,tabSucc,0,&graphe->noeuds[4]);
free(tabPred);
free(tabSucc);
// Noeud: 6
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[3];
tabPred[1]=&graphe->noeuds[6];
tabSucc[0]=&graphe->noeuds[4];
tabSucc[1]=&graphe->noeuds[7];
nouveauNoeud(5,2,2,tabPred,tabSucc,0,&graphe->noeuds[5]);
free(tabPred);
free(tabSucc);
// Noeud: 7
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[4];
tabPred[1]=&graphe->noeuds[7];
tabSucc[0]=&graphe->noeuds[3];
tabSucc[1]=&graphe->noeuds[5];
nouveauNoeud(6,2,2,tabPred,tabSucc,0,&graphe->noeuds[6]);
free(tabPred);
free(tabSucc);
// Noeud: 8
tabPred=(NoeudGraphe**)malloc(2*sizeof(NoeudGraphe*));
tabSucc=(NoeudGraphe**)malloc(3*sizeof(NoeudGraphe*));
tabPred[0]=&graphe->noeuds[3];
tabPred[1]=&graphe->noeuds[6];
tabSucc[0]=&graphe->noeuds[2];
tabSucc[1]=&graphe->noeuds[5];
tabSucc[2]=&graphe->noeuds[2];
nouveauNoeud(7,2,3,tabPred,tabSucc,0,&graphe->noeuds[7]);
free(tabPred);
free(tabSucc);
}
/* Fonction principale */
int main(void){
Graphe graphe;
int i,complexite1,complexite2,reponse;
do{
printf("Entrez le nombre de noeuds du graphe que vous desirez
(choix entre 4,6,8 et 10 noeuds)\n");
scanf("%d",&reponse);
}while((reponse!=4)&&(reponse!=6)&&(reponse!=8)&&(reponse!=10));
switch(reponse){
case 4:{
graphe4noeuds(&graphe);
break;
}
case 6:{
graphe6noeuds(&graphe);
break;
}
case 8:{
graphe8noeuds(&graphe);
break;
}
case 10:{
graphe10noeuds(&graphe);
break;
}
}
complexite2=dfs(&graphe);
printf("\t\t ----------\n");
printf("\t\t| Graphe 1 |\n");
printf("\t\t ----------\n");
printf("\nVal noeud
Nbr pred
Nbr succ\n");
printf("---------------------------------\n");
for(i=0;i<graphe.nbNoeuds;i=i+1){
printf("
%d
%d
%d\n",
graphe.noeuds[i].valeur,graphe.noeuds[i].nbPred,
graphe.noeuds[i].nbSucc);
}
printf("\nNb SuccTemp
Numerotation
Num prefixe
Num suffixe\n");
printf("------------------------------------------------------\n");
for(i=0;i<graphe.nbNoeuds;i=i+1){
printf("
%d
%d
%d
%d\n",
graphe.noeuds[i].nbSuccTemp,graphe.noeuds[i].numerotation,
graphe.noeuds[i].prefixe,graphe.noeuds[i].suffixe);
}
switch(reponse){
case 4:{
graphe4noeuds(&graphe);
break;
}
case 6:{
graphe6noeuds(&graphe);
break;
}
case 8:{
graphe8noeuds(&graphe);
break;
}
case 10:{
graphe10noeuds(&graphe);
break;
}
}
complexite1=kosarajuSharir(&graphe);
printf("\n\n\n\t\t ----------\n");
printf("\t\t| Graphe 2 |\n");
printf("\t\t ----------\n");
printf("\nVal noeud
Nbr pred
Nbr succ\n");
printf("-------------------------------\n");
for(i=0;i<graphe.nbNoeuds;i=i+1){
printf("
%d
%d
%d\n",
graphe.noeuds[i].valeur,graphe.noeuds[i].nbPred,
graphe.noeuds[i].nbSucc);
}
printf("\nNb SuccTemp
Numerotation
Num prefixe
Num suffixe\n");
printf("------------------------------------------------------\n");
for(i=0;i<graphe.nbNoeuds;i=i+1){
printf("
%d
%d
%d
%d\n",
graphe.noeuds[i].nbSuccTemp,graphe.noeuds[i].numerotation,
graphe.noeuds[i].prefixe,graphe.noeuds[i].suffixe);
}
printf("\nLa complexite de kosaraju sharir est : %d\n", complexite1);
printf("\nLa complexite de l'algorithme DFS est : %d\n",
complexite2);
free(graphe.noeuds);
}
III/ Résultats théoriques
Nous avons généré quatre graphes avec un nombre de noeuds différents à chaque fois pour
tester si notre programme fonctionne bien que nous ayons des problèmes au niveau de l’exécution de
l’algorithme de Kosaraju-Sharir.
1) Résultat théorique sur un graphe à 4 nœuds
Détermination des composantes fortement connexes.
G = (X, U)
0
1
3
2
Application de l’algorithme DFS sur le graphe G selon la manière vue en travaux dirigés :
(Remarque : x représente le nœud traité et (x), l’ensemble des successeurs de x.)
Préfixe
Suffixe
x
(x)
1
2
3
4
4
3
2
1
0
1
2
3
1
2
1, 3
0, 1
Graphe réduit résultant du DFS sur G :
0
1
2
3
Soit le graphe G’ = (X, U’) obtenu en inversant les arcs du graphe G :
0
1
3
2
Application de l’algorithme DFS sur le graphe G’ en commençant par le sommet de plus grand numéro
suffixe et en itérant ce processus à partir du sommet non marqué de plus grand numéro suffixe :
Préfixe
Suffixe
x
(x)
1
2
3
4
4
3
2
1
0
2
1
3
2, 3
1
0, 3
2
Graphe réduit résultant du DFS sur G’ :
0
2
1
3
2) Résultat théorique sur un graphe à 6 nœuds
Détermination des composantes fortement connexes.
G = (X, U)
0
1
3
2
4
5
Application de l’algorithme DFS sur le graphe G selon la manière vue en travaux dirigés :
(Remarque : x représente le nœud traité et (x), l’ensemble des successeurs de x.)
Préfixe
Suffixe
x
(x)
1
2
3
4
5
6
6
5
4
3
2
1
0
1
2
3
5
4
1
2
0, 3
5
4
3
Graphe réduit résultant du DFS sur G :
0
1
2
3
4
5
Soit le graphe G’ = (X, U’) obtenu en inversant les arcs du graphe G :
0
1
3
2
4
5
Application de l’algorithme DFS sur le graphe G’ en commençant par le sommet de plus grand numéro
suffixe et en itérant ce processus à partir du sommet non marqué de plus grand numéro suffixe :
Préfixe
Suffixe
x
(x)
1
2
3
4
5
6
6
5
4
3
2
1
0
2
1
5
3
4
2
1, 3, 4
0, 5
3
2, 4
5
Graphe réduit résultant du DFS sur G’ :
0
2
1
5
3
4
3) Résultat théorique sur un graphe à 8 nœuds
Détermination des composantes fortement connexes.
G = (X, U)
1
4
2
0
3
5
7
6
Application de l’algorithme DFS sur le graphe G selon la manière vue en travaux dirigés :
(Remarque : x représente le nœud traité et (x), l’ensemble des successeurs de x.)
Préfixe
Suffixe
x
(x)
1
2
3
4
5
6
7
8
8
7
6
5
4
3
2
1
0
3
1
4
6
5
7
2
3
5, 1
2, 4
2, 6
3, 5
7
0, 6, 2
3, 7
Graphe réduit résultant du DFS sur G :
0
3
1
4
6
5
7
2
Soit le graphe G’ = (X, U’) obtenu en inversant les arcs du graphe G :
1
4
2
0
3
5
7
6
Application de l’algorithme DFS sur le graphe G’ en commençant par le sommet de plus grand numéro
suffixe et en itérant ce processus à partir du sommet non marqué de plus grand numéro suffixe :
Préfixe
Suffixe
x
(x)
1
8
0
7
2
3
4
5
6
7
8
7
5
4
3
2
1
6
7
5
6
4
1
3
2
2, 5
0, 6
4, 7
5, 1
3
0, 6,
1, 3, 4, 7
Graphe réduit résultant du DFS sur G’ :
0
7
5
6
4
1
3
2
4) Résultat théorique sur un graphe à 10 nœuds
Détermination des composantes fortement connexes.
G = (X, U)
2
3
4
1
5
0
6
9
8
7
Application de l’algorithme DFS sur le graphe G selon la manière vue en travaux dirigés :
(Remarque : x représente le nœud traité et (x), l’ensemble des successeurs de x.)
Préfixe
Suffixe
x
(x)
1
2
3
4
5
6
7
8
9
10
10
9
8
7
6
5
4
3
2
1
0
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
0
Graphe réduit résultant du DFS sur G :
0
1
2
3
4
5
6
7
Soit le graphe G’ = (X, U’) obtenu en inversant les arcs du graphe G :
8
9
2
3
4
1
5
0
6
9
8
7
Application de l’algorithme DFS sur le graphe G’ en commençant par le sommet de plus grand numéro
suffixe et en itérant ce processus à partir du sommet non marqué de plus grand numéro suffixe :
Préfixe
Suffixe
x
(x)
1
2
3
4
5
6
7
8
9
10
10
9
8
7
6
5
4
3
2
1
0
9
8
7
6
5
4
3
2
1
9
8
7
6
5
4
3
2
1
0
Graphe réduit résultant du DFS sur G’ :
0
9
8
7
6
5
4
3
2
1
Conclusion
En définitif, le fait de programmer un algorithme de recherche des composantes fortement
connexes comme celui de Kosaraju-Sharir nous a permis une meilleure compréhension du
fonctionnement de l’algorithme en question.
Cependant, nous avons été confrontés à quelques difficultés. En effet dans l’implémentation de
l’algorithme de Kosaraju-Sharir nous avons des problèmes de pointeurs. Effectivement, le graphe de
quatre nœuds fonctionne comme il se doit mais les autres génèrent des erreurs d’exécution.
Nous espérons tout de même que la théorie de notre programme soit conforme à vos attentes.
Nous tenons à remercier tout particulièrement nos professeurs d’informatique Monsieur
LETOCART Lucas et Madame TOULOUSE Sophie.
Téléchargement