Parcours en profondeur : écriture du code en Python
Écriture d’une classe Graphe
L’objectif de cette partie est l’écriture du code modélisant un graphe orienté. La représentation choisie est celle d’un dictionnaire de successeurs (en cours et dans le document 15,2 on a étudié les représentations par des matrice et liste de successeurs).
La représentation par un dictionnaire de successeurs présente de nombreux avantages. Par exemple,
les sommets peuvent être des entiers ou des chaînes de caractères quelconques ;
La complexité de la liste des successeurs est directement proportionnelle au nombre de successeurs pour un sommet donné. L’occupation mémoire est donc faible si les sommets possèdent peu de successeurs. Remarque : dans le cas d’une matrice d’adjacence, la taille est fixe et comporte $N^2$ éléments si le nombre de sommets est égal à $N$.
Remarque
Contrairement à ce qui a été fait dans le document 15,2, la classe qui va être implémentée ici permettra d’initialiser un graphe vide, puis de le constituer progressivement.
Initialiser la classe Graphe. La méthode __init__ a pour seule fonction l’affectation d’un dictionnaire vide à l’attribut succ.
Créer la méthode ajouter_sommet dont la spécification est :
1
2
3
4
5
6
7
defajouter_sommet(self:Graphe,s:Union[int,str])->None:"""
Ajoute le sommet s (entier ou chaîne de caractères) au graphe
s'il n'est pas déjà présent.
s est une clé du dictionnaire succ. Sa valeur associée par défaut
est une liste vide.
"""
Solution
1
2
3
4
5
6
7
8
9
defajouter_sommet(self:Graphe,s:Union[int,str])->None:"""
Ajoute le sommet s (entier ou chaîne de caractères) au graphe
s'il n'est pas déjà présent.
s est une clé du dictionnaire succ. Sa valeur associée par défaut
est une liste vide.
"""ifsnotinself.succ.keys():self.succ[s]=[]
Créer la méthode ajouter_arc dont la spécification est :
1
2
3
4
5
defajouter_arc(self:Graphe,s1:Union[int,str],s2:Union[int,str])->None:"""
Ajoute s2 à la liste des successeurs de s1. Si s1 et s2 n'existent pas, ils sont
créés en utilisant la méthode ajouter_sommet.
"""
Solution
1
2
3
4
5
6
7
8
9
defajouter_arc(self:Graphe,s1:Union[int,str],s2:Union[int,str])->None:"""
Ajoute s2 à la liste des successeurs de s1. Si s1 et s2 n'existent pas, ils sont
créés en utilisant la méthode ajouter_sommet.
"""self.ajouter_sommet(self,s1)self.ajouter_sommet(self,s2)ifs2notinself.succ[s1]:self.succ[s1].append(s2)
Créer la méthode existe_arc dont la spécification est :
1
2
3
4
defexiste_arc(self:Graphe,s1:Union[int,str],s2:Union[int,str])->bool:"""
Retourne True si l'arc s1 -> s2 existe.
"""
Solution
1
2
3
4
5
defexiste_arc(self:Graphe,s1:Union[int,str],s2:Union[int,str])->bool:"""
Retourne True si l'arc s1 -> s2 existe.
"""returns2inself.succ[s1]
Créer la méthode liste_sommets dont la spécification est :
1
2
3
4
defliste_sommets(self:Graphe)->List[Union[int,str]]:"""
Retourne la liste des sommets du graphe.
"""
Solution
1
2
3
4
5
defliste_sommets(self:Graphe)->List[Union[int,str]]:"""
Retourne la liste des sommets du graphe.
"""returnlist(self.succ.keys())
Créer la méthode nbre_sommets dont la spécification est :
1
2
3
4
5
defnbre_sommets(self:Graphe)->int:"""
Retourne le nombre de sommets du graphe.
Utilise la méthode liste_sommets.
"""
Solution
1
2
3
4
5
6
defnbre_sommets(self:Graphe)->int:"""
Retourne le nombre de sommets du graphe.
Utilise la méthode liste_sommets.
"""returnlen(self.liste_sommets())
Créer la méthode liste_successeurs dont la spécification est :
1
2
3
4
defliste_successeurs(self:Graphe,s:Union[int,str])->List[Union[int,str]]:"""
Retourne la liste des successeurs du sommet s1.
"""
Solution
1
2
3
4
5
defliste_successeurs(self:Graphe,s:Union[int,str])->List[Union[int,str]]:"""
Retourne la liste des successeurs du sommet s1.
"""returnself.succ[s1]
Dans la partie principale du programme, entrer les instructions qui permettent de coder le graphe suivant :
graph TD
A(0) --> B(1)
B --> C(2)
A --> D(3)
D --> B
Reprendre la fonction parcours_profondeur proposée dans le document 15,3 et la transformer en méthode de la classe Graphe. Sa nouvelle spécification est alors :
1
2
3
4
5
6
7
defparcours_profondeur(self:Graphe,vus:List[Union[int,str]],s:Union[int,str])->None:"""
Parcours en profondeur depuis le sommet s.
Cette méthode prend en argument la liste des sommets déjà visités. Lors du premier appel
cette liste doit être vide.
Le parcours est accessible par lecture de la liste vus.
"""
Remarque.
Attention, j’ai modifié le nom d’une méthode : voisins s’appelle désormais liste_successeurs.
Solution
1
2
3
4
5
6
7
8
9
10
11
defparcours_profondeur(self:Graphe,vus:List[Union[int,str]],s:Union[int,str])->None:"""
Parcours en profondeur depuis le sommet s.
Cette méthode prend en argument la liste des sommets déjà visités. Lors du premier appel
cette liste doit être vide.
Le parcours est accessible par lecture de la liste vus.
"""ifsnotinvus:vus.append(s)forvinself.liste_successeurs(s):parcours_profondeur(self,vus,v)
Créer la méthode existe_chemin dont la spécification est :
1
2
3
4
defexiste_chemin(self:Graphe,s1:Union[int,str],s2:Union[int,str])->bool:"""
Retourne True s'il existe un chemin depuis s1 jusqu'à s2.
"""
Solution
1
2
3
4
5
6
7
defexiste_chemin(self:Graphe,s1:Union[int,str],s2:Union[int,str])->bool:"""
Retourne True s'il existe un chemin depuis s1 jusqu'à s2.
"""vus=[]self.parcours_profondeur(self,vus,s1)returns2invus
Vérifier le code précédent en utilisant le graphe proposé à la question 8.
Comment construire le chemin entre s1 et s2 ?\
Remplacer, dans la méthode parcours_profondeur la liste vus par un dictionnaire dont les clés sont les sommets visités et les valeurs associées sont les sommets prédécesseurs.
Attribuer la valeur None au sommet de départ.
Une fois le parcours en profondeur achevé, on peut vérifier qu’il existe un chemin en vérifiant si les deux sommets sont dans la liste des valeurs du dictionnaire.
Une fois le parcours en profondeur achevé, on peut donner le parcours en remontant le dictionnaire depuis le sommet d’arrivée.
Modifier le code des méthodes parcours_profondeur et existe_chemin à partir des consignes ci-dessus.
Créer la méthode chemin_entre dont la spécification est :
1
2
3
4
defchemin_entre(self:Graphe,s1:Union[int,str],s2:Union[int,str])->List[Union[int,str]]:"""
Vérifie que le chemin entre s1 et s2 existe puis le retourne sous la forme d'une liste.
"""
Parcours en profondeur basé sur la structure pile
Écrire le code de la classe Pile. En plus de la méthode __init__ cette classe doit posséder les méthodes est_vide, empiler et depiler.
Adapter le code de la fonction proposée dans le document document 15,3 afin de la transformer en méthode de la classe Graphe.