Attention, ce sont des propositions de correction, cela veut dire qu'il existe d'autres solutions et que les solutions proposées ici ne sont pas obligatoirement les meilleures ! Il s'agit des corrections qui ont été proposées en TD.
Pour les corrections Java (feuille 1 et 2) il faut copier le fichier TextWindow.class dans le même répertoire que les autres fichiers.
Vous pouvez aussi copier le fichier source Java TextWindow.java dans le même répertoire que les autres fichiers et le compiler sur votre ordinateur.
Type LC {
Champ info Type Élément
Champ suivant Type LC
}
Sous-programme LC vide ()
Début
retourner null
Fin
Sous-programme LC ajouter (LC p, Élément e)
Variables q Type LC
Début
q ← nouveau LC
q.info ← e
q.suivant ← p
retourner q
Fin
Sous-programme Élément tête (LC p)
Début
retourner p.info
Fin
Sous-programme LC reste (LC p)
Début
retourner p.suivant
Fin
Sous-programme Booléen estVide (LC p)
Début
retourner p = null
Fin
Sous-programme Booléen appartient (LC p, Élément x)
Début
TantQue (non estVide (p)) Faire
Si (tête (p) = x) Alors
retourner vrai
FinSi
FinTantQue
retourner faux
Fin
une version récursive :
Sous-programme Booléen appartient (LC p, Élément x)
Début
Si (estVide (p)) Alors
retourner faux
Sinon
Si (tête (p) = x) Alors
retourner vrai
Sinon
retourner appartient (reste (p), x)
FinSi
FinSi
Fin
Sous-programme LC supprimer1oc (LC p, Élément x)
Variables trouvé type Booléen
Variables q type LC
Début
Si (estVide (p)) Alors
retourner p
Sinon
Si (tête (p) = x) Alors
retourner reste (p)
Sinon
trouvé ← faux
q ← p
TantQue ((non trouvé) et (non estVide (reste (q)))) Faire
Si (tête (reste (q)) = x) Alors
q.suivant ← reste (reste (q))
trouvé ← vrai
Sinon
q ← reste(q)
FinSi
FinTantQue
retourner p
FinSi
FinSi
Fin
L'un des problèmes de la version itérative ci-dessus est que si
p1 et p2 sont deux variables de type LC et x est un
Élément alors l'instruction
Sous-programme LC supprimer1oc (LC p, Élément x)
Variables trouvé type Booléen
Variables q, r type LC
Début
Si (estVide (p)) Alors
retourner p
Sinon
Si (tête (p) = x) Alors
retourner reste (p)
Sinon
trouvé ← faux
r ← nouveau LC
r.info ← tête (p)
q ← reste (p)
p ← r
TantQue ((non trouvé) et (non estVide (q))) Faire
Si (tête (q) = x) Alors
r.suivant ← q.suivant
trouvé ← vrai
Sinon
r.suivant ← nouveau LC
r ← r.suivant
r.info ← tête (q)
q ← q.suivant
FinSi
FinTantQue
Si (non trouvé) Alors
r.suivant ← vide ()
FinSi
retourner p
FinSi
FinSi
Fin
une version récursive en recopiant le début de la liste :
Sous-programme LC supprimer1oc (LC p, Élément x)
Début
Si (estVide (p)) Alors
retourner p
Sinon
Si (tête (p) = x) Alors
retourner reste (p)
Sinon
retourner ajouter (supprimer1oc (reste (p), x), tête (p))
FinSi
FinSi
Fin
Sous-programme LC supprimer (LC p, Élément x)
Début
Si (estVide (p)) Alors
retourner p
Sinon
Si (tête (p) = x) Alors
retourner supprimer (reste (p), x)
Sinon
retourner ajouter (supprimer (reste (p), x), tête (p))
FinSi
FinSi
Fin
Version itérative en modifiant seulement les liens :
Sous-programme LC supprimer (LC p, Élément x)
Variables q type LC
Début
TantQue ((non EstVide(p)) et (tête (p) = x)) Faire
p ← reste (p)
FinTantQue
Si (non estVide (p)) Alors
q ← p
TantQue (non estVide (reste (q))) Faire
Si (tête (reste (q)) = x) Alors
q.suivant ← reste (reste (q))
Sinon
q ← reste(q)
FinSi
FinTantQue
FinSi
retourner p
Fin
Version itérative en créant une nouvelle liste :
Sous-programme LC supprimer (LC p, Élément x)
Variables q, r type LC
Début
TantQue ((non EstVide(p)) et (tête (p) = x)) Faire
p ← reste (p)
FinTantQue
Si (non estVide (p)) Alors
r ← nouveau LC
r.info ← tête (p)
q ← reste (p)
p ← r
TantQue (non estVide (q)) Faire
Si (tête (q) ≠ x) Alors
r.suivant ← nouveau LC
r ← r.suivant
r.info ← tête (q)
FinSi
q ← q.suivant
FinTantQue
r.suivant ← vide ()
FinSi
retourner p
Fin
Sous-programme Entier nbÉlément (LC p)
Variable n type Entier
Début
n ← 0
TantQue (non estVide (p)) Faire
n ← n + 1
p ← reste (p)
FinTantQue
retourner n
Fin
Version récursive :
Sous-programme Entier nbÉlément (LC p)
Début
Si (estVide (p)) Alors
retourner 0
Sinon
retourner 1 + nbÉlément (reste (p))
FinSI
Fin
L'affichage est
32->16->8->4->2->Fin
À la fin, la variable p0 désigne la liste 2, p1 la liste 4,2 et r la liste vide.
Type LDC {
Champ info Type Élément
Champ prec Type LDC
Champ suiv Type LDC
}
Sous-Programme LDC LCversLDC (LC p)
Variables q, r Type LDC
Début
Si (estVide (p)) Alors
retourner null
Sinon
q ← nouveau LDC
r ← q
q.info ← tête (p)
q.prec ← null
p ← reste (p)
TantQue (non estVide (p)) Faire
q.suiv ← nouveau LDC
q.suiv.prec ← q
q ← q.suiv
q.info ← tête (p)
p ← reste (p)
FinTantQue
q.suiv ← null
retourner r
FinSi
Fin
Tri par sélection en échangeant les infos des maillons :
Sous-Programme LC max (LC p)
Variables m Type LC
Début
m ← p
p ← reste (p)
TantQue (non estVide (p)) Faire
Si (tête (m) < tête (p)) Alors
m ← p
FinSi
p ← reste (p)
FinTantQue
retourner m
Fin
Sous-Programme LC trier (LC p)
Variables q, m Type LC
Variables aux Type Élément
Début
q ← p
Si (non estVide (p)) Alors
TantQue (non estVide (reste(p))) Faire
m ← max (p)
aux ← p.info
p.info ← m.info
m.info ← aux
p ← reste (p)
FinTantQue
FinSi
retourner q
Fin
Tri quickSort par modification des liens entre les maillons :
Sous-Programme LC quickSort (LC p)
Variables pivot, pp, pg, q Type LC
Début
Si (non estVide (p)) Alors
/* on prend le premier élément de la liste comme pivot */
pivot ← p
p ← reste (p)
/* on fait la liste des plus petits pp et la liste des plus grands pg */
pp ← vide ()
pg ← vide ()
TantQue (non estVide (p)) Faire
q ← reste (p)
Si (tête (p) < tête (pivot)) Alors
p.suivant ← pp
pp ← p
Sinon
p.suivant ← pg
pg ← p
FinSi
p ← q
FinTantQue
/* on trie la liste des plus petits pp et la liste des plus grands pg */
pp ← quickSort (pp)
pg ← quickSort (pg)
/* on met bout à bout la liste pg, le pivot et la liste pp */
pivot.suivant ← pp
Si (estVide (pg)) Alors
p ← pivot
Sinon
p ← pg
TantQue (non estVide (reste (pg))) Faire
pg ← reste (pg)
FinTantQue
pg.suivant ← pivot
FinSi
FinSi
retourner p
Fin
On a une première cellule qui contient le nombre d'élément de la liste et un pointeur vers le dernier élément de la liste
On réutilise le type LC pour stocker les éléments de la liste.
Le type LCirc :
Type LCirc {
Champ taille Type Entier
Champ dernier Type LC
}
Les algorithmes :
Sous-programme LCirc créerLCirc ()
Variables lc Type LCirc
Début
lc ← nouveau LCirc
lc.taille ← 0
lc.dernier ← null
retourner lc
Fin
Attention quand on ajoute, on souhaite que la liste reste triée en ordre croissant.
Sous-programme LCirc ajouterLCirc (LCirc lc, Élément e)
Variables p, q Type LC
Début
p ← nouveau LC
p.info ← e
Si (videLCirc (lc)) Alors
/* si la liste était vide alors e devient le seul élément de la liste */
p.suivant ← p
lc.dernier ← p
Sinon
Si (lc.dernier.info ≤ e) Alors
/* si e est supérieur ou égal à tous les éléments de la liste, il devient le dernier élément */
p.suivant ← lc.dernier.suivant
lc.dernier.suivant ← p
lc.dernier ← p
Sinon
/* sinon on recherche l'endroit où insérer e puis on l'insère */
q ← lc.dernier
TantQue (q.suivant.info < e) Faire
q ← q.suivant
FinTantQue
p.suivant &larr q.suivant
q.suivant &larr p
FinSi
FinSi
/* la liste a un élément de plus */
lc.taille ← lc.taille + 1
retourner lc
Fin
Pour retirer, on peut utiliser le fait que la liste est triée...
Sous-programme LCirc retirerLCirc (LCirc lc, Élément e)
Variables p, q Type LC
Début
Si (non videLCirc (lc)) Alors
Si (e ≤ lc.dernier.info) Alors
/* si l'élément à retirer n'est pas plus grand que le dernier élément de la liste */
Si (lc.dernier.info = lc.dernier.suivant.info) Alors
/* si tous les éléments de la liste sont identiques */
Si (lc.dernier.info = e) Alors
/* s'il s'agit de l'élément à retirer */
lc.dernier = null
lc.taille = 0
FinSi
Sinon
/* si tous les éléments de la liste ne sont pas identiques */
/* p va pointer sur l'élément qui précède celui à retirer */
p ← lc.dernier
TantQue (p.suivant.info < e) Faire
p ← p.suivant
FinTantQue
/* q va pointer sur l'élément qui suit celui à retirer */
/* et en même temps on décompte les éléments retirés */
q ← p.suivant
TantQue (q.info = e) Faire
q ← q.suivant
lc.taille ← lc.taille - 1
FinTantQue
/* le suivant de p est maintenant q */
p.suivant ← q
Si (lc.dernier.info = e) Alors
/* si l'élément à retirer était le dernier on a un nouveau dernier qui est p */
lc.dernier ← p
FinSi
FinSi
FinSi
FinSi
retourner lc
Fin
Sous-programme Booléen videLCirc (LCirc lc)
Début
retourner lc.taille = 0
Fin
Type EntierBinaire {
Champ bit Type Caractère
Champ suivant Type EntierBinaire
}
Pour vérifier qu'une liste EntierBinaire correspond à la représentation binaire d'un entier naturel, on vérifie que tous ses champs bit sont des '0' ou des '1' :
Sous-programme Booléen vérifier (EntierBinaire e)
Début
Si (e = null) Alors
retourner vrai
Sinon
Si ((e.bit ≠ '0') et (e.bit ≠ '1')) Alors
retourner faux
Sinon
retourner vérifier (e.suivant)
FinSi
FinSi
Fin
Pour convertir un EntierBinaire
bi...bk+1bkbk-1...b0 en Entier on va utiliser un
sous-programme récursif convertir2 qui prend en paramètre l'EntierBinaire
bkbk-1...b0 et la conversion v de
l'EntierBinaire bi...bk+1 car :
convertir2 (bkbk-1...b0, v) =
convertir2 (bk-1...b0, 2 * v + bk) =
convertir2 (bi...bk+1bkbk-1...b0, 0)
Sous-programme Entier convertir (EntierBinaire e)
Début
retourner convertir2 (e, 0)
Fin
Sous-programme Entier convertir2 (EntierBinaire e, Entier v)
Début
Si (e = null) Alors
retourner v
Sinon
Si (e.bit = '0') Alors
retourner convertir2 (e.suivant, 2 * v)
Sinon
retourner convertir2 (e.suivant, 2 * v + 1)
FinSi
FinSi
Fin
Type Pile {
Champ info Type Élément
Champ lien Type Pile
}
Sous-programme Pile créerPile ()
Début
retourner null
Fin
Sous-programme Pile empiler (Pile p, Élément e)
Variables q Type Pile
Début
q ← nouveau Pile
q.info ← e
q.lien ← p
retourner q
Fin
Sous-programme Pile dépiler (Pile p)
Début
retourner p.lien
Fin
Sous-programme Élément sommet (Pile p)
Début
retourner p.info
Fin
Sous-programme Booléen pileVide (Pile p)
Début
retourner p = null
Fin
Une version itérative du sous-programme hauteur :
Sous-programme Entier hauteur (Pile p)
Variables h Type Entier
Début
h ← 0
TantQue (non pileVide (p)) Faire
p ← p.lien
h ← h + 1
FinTantQue
retourner h
Fin
Une version récursive du sous-programme hauteur :
Sous-programme Entier hauteur (Pile p)
Début
Si (pileVide (p)) Alors
retourner 0
Sinon
retourner 1 + hauteur (dépiler (p))
Fin
Une version itérative du sous-programme affichePile :
Sous-programme affichePile (Pile p)
Début
TantQue (non pileVide (p)) Faire
afficher (sommet (p))
p ← dépiler (p)
FinTantQue
Fin
Une version récursive du sous-programme affichePile :
Sous-programme affichePile (Pile p)
Début
Si (non pileVide (p)) Alors
afficher (sommet (p))
affichePile (dépiler (p))
FinSi
Fin
La traduction en Java, avec les classes Maillon et Pile.
On veut vérifier uniquement que le parenthésage est correct et on va donc ignorer tous les caractères de la chaîne qui ne sont ni parenthèse ni crochet.
Sous-programme Booléen vérifier (ChaînedeCar x)
Variables correct Type Booléen
Variables p Type Pile
Variables i Type Entier
Variables c Type Caractère
début
correct ← vrai
p ← créerPile ()
i ← 0
TantQue (correct et i < longueur (x)) Faire
c ← carIndice (x, i)
Si (c = '(' ou c = '[') Alors
p ← empiler (p, c)
Sinon
Si (c = ')') Alors
Si (pileVide (p)) Alors
correct ← faux
Sinon
correct ← sommet (p) = '('
p ← dépiler (p)
FinSi
Sinon
Si (c = ']') Alors
Si (pileVide (p)) Alors
correct ← faux
Sinon
correct ← sommet (p) = '['
p ← dépiler (p)
FinSi
FinSi
Finsi
FinSi
i ← i + 1
FinTantQue
Si (correct) Alors
Si (pileVide (p)) Alors
afficher ("parenthésage correct")
Sinon
afficher ("non refermée(s) :")
affichePile (p)
correct ← faux
FinSi
Sinon
afficher (c, "inattendue")
FinSi
retourner correct
fin
La traduction en Java : la classe S2F04E02 (pour pouvoir l'utiliser vous avez besoin de la classe Pile du fichier S2F04E01.java).
La traduction en Java : on réutilise la classe Pile de l'exercice 1 pour les piles de caractères et on définit la classe PileEnt pour les piles d'entiers.
On peut utiliser, comme pour les Piles, des listes simplement chaînées (dans le style LC) ou, pour avoir un accès rapide au début et à la fin de la File, on peut utliser des listes circulaires (dans le style LCirc). Je donne la correction avec des listes circulaires : la classe File en Java.
Récursif :
Sous-programme File inverserRec (File f)
Début
Si (fileVide (f)) Alors
retourner créerFile ()
Sinon
retourner enfiler (inverserRec (défiler (f)), tête (f))
FinSi
Fin
Itératif avec une Pile :
Sous-programme File inverserIt (File f)
Variable p Type Pile
Début
p ← créerPile ()
TantQue (non fileVide (f)) Faire
p ← empiler (p, tête (f))
f ← défiler (f)
FinTantQue
f ← créerFile ()
TantQue (non pileVide (p)) Faire
f ← enfiler (f, sommet (p))
p ← dépiler (p)
FinTantQue
retourner f
Fin
Le programme Java :S2F04E05.
type ABin {
Champ info Type Élément
Champ filsG Type ABin
Champ filsD Type ABin
}
Sous-programme ABin créerABin ()
Début
retourner null
Fin
Sous-programme ABin enracinerABin (Élément e, ABin ag, ABin ad)
Variable a Type ABin
Début
a ← nouveau ABin
a.info ← e
a.filsG ← ag
a.filsD ← ad
retourner a
Fin
Sous-programme Booléen estVideABin (ABin a)
Début
retourner a = null
Fin
Sous-programme Élément racineABin (ABin a)
Début
retourner a.info
Fin
Sous-programme ABin gaucheABin (ABin a)
Début
retourner a.filsG
Fin
Sous-programme ABin droiteABin (ABin a)
Début
retourner a.filsD
Fin
Sous-programme Booléen estFeuilleABin (ABin a)
Début
Si (estVideABin (a)) Alors
retourner faux
Sinon
retourner estVideABin (gaucheABin (a)) et estVideABin (droiteABin (a))
FinSi
Fin
Sous-programme Entier tailleABin (ABin a)
Début
Si (estVideABin (a)) Alors
retourner 0
Sinon
retourner 1 + tailleABin (gaucheABin (a)) + tailleABin (droiteABin (a))
FinSi
Fin
Sous-programme Entier hauteurABin (ABin a)
Variables hg, hd Type Entier
Début
Si (estVideABin (a)) Alors
retourner 0
Sinon
hg ← hauteurABin (gaucheABin (a))
hd ← hauteurABin (droiteABin (a))
Si (hd < hg) Alors
retourner 1 + hg
Sinon
retourner 1 + hd
FinSi
FinSi
Fin
Sous-programme Entier nbFeuilleABin (ABin a)
Début
Si (estVideABin (a)) Alors
retourner 0
Sinon
Si (estFeuilleABin (a)) Alors
retourner 1
Sinon
retourner nbFeuilleABin (gaucheABin (a)) + nbFeuilleABin (droiteABin (a))
FinSi
FinSi
Fin
Le programme Java : S2F04E06.java (attention, cette manière de programmer la classe ABin n'est pas efficace).
Merci d'envoyer vos remarques à