Correction de l’exercice 31.
Il restepince-moi je rêve ce sujet est trop facile.
Correction de l’exercice 32.
1. void pilePaireImpaire(pile_t P1, pile_t P2, pile_t P3){
int aux;
viderPile(P2);
viderPile(P3);
while(pileVide(P1)==0){
aux=depiler(P1);
if( (aux&1)==1)
empiler(P2, aux);
else
empiler(P3, aux);
}
while(pileVide(P3)==0){
aux=depiler(P3);
empiler(P2, aux);
}
}
void interclasser(file_t f1, file_t f2, file_t f3){
element_t x;
while ( !EstVide(f1) && !EstVide(f2) ){
if ( tete(f1) < tete(f2) ) { x = retirer(f1);
} else {
x = retirer(f2);
}
ajouter(f3, x);
}
while (!EstVide(f1)) { ajouter(f3, retirer(f1));
}
while (!EstVide(f2)) { ajouter(f3, retirer(f2));
} } 2. Scinder
void scinder(file_t f1, file_t f2, file_t f3) { int sw = 1;
while (!Estvide(f1)) { x = retirer(f1);
if (sw) {
ajouter(f2, x);
sw = 0;
} else {
ajouter(f3, x);
sw = 1;
} } } 3. Le tri
void tri_fusion (file_t f1) { file_t f2, file_t f3;
if (!EstVide(f1)) { f2 = nouvelleFile();
f3 = nouvelleFile();
scinder(f1, f2, f3);
if (!EstVide(f2)) tri_fusion(f2);
if (!EstVide(f3)) tri_fusion(f3);
interclasser(f2, f3, f1);
detruireFile(f2);
detruireFile(f3);
} }
4. La consommation mémoire réside dans les appels récursifs. On crée notamment deux empla-cements mémoires à chaque appel à tri_fusionà quoi il faut ajouter la mémoire occupée par l’appel de fonction proprement dit (valeur du paramètre, adresse de retour, etc.). Les appels forment un arbre binaire à
N
noeuds. Le nombre maximal d’appel imbriqués est la hauteur de l’arbre, qui est enlog N
. L’empreinte mémoire est donc de l’ordre delog N
ce qui est donc mieux que d’être de l’ordre deN
.Correction de l’exercice 36.
1. liste_t entrelacement(liste_t liste1, liste_t liste2){
if (liste1 == NULL) return liste2;
if (liste2 == NULL) return liste1;
if ( cmpListe(liste1, liste2)>=0 ){
void deplacer(pile_t p, pile_t q) { empiler(q,depiler(p));
/* ou encore: if (!EstVide(p)) empiler(q,depiler(p)); */
}
2. Pour
n = 3
:3. Déplacements possibles. Deux à partir de
p
puisque1
peut être posé n’importe où (deux destinations possibles. Et un seul déplacement à partir d’un des autres piquet : sid
etd
′sont les deux disques aux sommet des deux autres piquets avecd < d
′ alorsd
′ ne peut pas être posé sur1
ou surd
, etd
peut seulement être posé surd
′. Deux même si l’une des autres piles est vide (c’est comme sid
′était le fond le la pile vide).4. Si on déplace un disque deux fois de suite ce n’est pas optimal, autant l’avoir posé à la bonne place dès la première fois.
5. Donc
1
est déplacé un coup sur deux. Comme il est déplacé en premier et en dernier et qu’il y a2
n−1
déplacements,1
est déplacé exactement2
n−1fois.6. Soit
1
occupe tour à toura, b, c, a, b, c, a, b, c, . . .
Soit1
occupe tour à toura, c, b, a, c, b, a, c, b, . . .
7. La séquence des positions de1
doit se terminer surc
. Dans les deux séquences précédentes, la positiona
correspond à un nombre de déplacements divisible par3
(0
déplacement pour la première position). S’il y ak
déplacements de1
, dans la séquencea, b, c, a, b, c, . . .
(respec-tivementa, c, b, a, c, b, . . .
) on doit avoirk mod 3 = 2
(respectivementk mod 3 = 1
), pour atterrir sur le piquetc
. Or il y a2
n−1déplacements du disque1
. Reste donc à déterminer le reste modulo3
de2
n−1en fonction den
pour savoir quelle séquence de déplacement choisir.Ce reste n’est jamais nul (c’est cohérent). Il peut être
1
(pourn = 1
) ou2
(pourn = 2
), et en remultipliant par deux pour passer à chaque fois aun
suivant, on obtient4 = 1 mod 3
(n
vaut3
), et on tombe sur un cycle (1
×2 = 2
,2
×2 = 4 = 1 mod 3
etc) . Pourn
pair il faut donc choisir la séquencea, b, c, . . .
et pourn
impair la séquencea, c, b, . . .
8. On est dans le cas
n
pair donc1
se déplace selon la séquence de positonsa, b, c, . . .
. Le déplacement qui vient d’être fait ne portait pas sur1
, on doit donc déplacer1
.56 2 autant de piles que de cartes c’est à dire
N
.2. La suite des cartes en haut des piles est croissante. Pour trouver l’emplacement d’une nou-velle carte, il suffit donc de chercher la dernière pile dont la carte du dessus
y
a une valeurinférieure à
x
et de poser la cartex
sur la pile suivante. Pour chercher cette pile, on cherche par dichotomiex
dans le tableau des têtes de piles. Ceci prend un nombre de comparaisons en log du nombre de piles. Comme il y a au plusN
piles, insérer une carte prendO(log N )
comparaisons. Donc insérerN
cartes prendO(N log N )
comparaisons.3. On remarque que si
x
vient d’être placé sur une pileT [j]
alors toute cartey
qui suitx
dansσ
et qui est plus grande quex
doit être placée après la pileT [j]
. En effet au moment de placerx
, toutes les piles avantT [j]
ont des cartes du dessus de valeur inférieure àx
. Ces valeurs du dessus, jusqu’àT [j]
incluse ne peuvent que diminuer par ajout de nouvelles cartes. Donc au moment de placery
, il n’est pas possible de le poser sur une des piles avantT [j + 1]
. Supposons quea
1< . . . < a
k est une sous-suite deσ
. Une fois quea
iest placé sur une pile,a
i+1est nécessairement placé sur une des piles suivantes. Il faut donc au moinsk
piles.4.
5. Si il y a une flêche d’un élément
x
vers élémenty
alors l’élémentx
est plus grand que l’élémenty
etx
a été posé aprèsy
. Ainsi une suite obtenue en suivant les flêches donne, en ordre inverse, une suite croissante d’éléments deσ
dans l’ordre de leur apparation dansσ
, c’est à dire une sous-suite croissante deσ
.6. Tout élément qui n’est pas dans la première pile possède une flêche vers un élément dans la pile juste avant. Prenons n’importe quel élément de la dernière pile
T [p
−1]
et suivons les flêches. Nous aurons alors une sous-suite croissante deσ
de longueurp
.7. La question précédente nous montre que le nombre de piles
p
formées par Réussite(σ
) est égal à la longueur d’au moins une sous-suite croissante deσ
, et donc quep
minorel(σ)
. Nous avons aussi montré (question 3) que quel que soit la stratégie le nombre de piles est toujours supérieur ou égal àl(σ)
. On en déduit l’égalitép = l(σ)
. D’autre part puisque toute stratégie forme au moinsl(σ)
piles et que Réussite en forme exactementl(σ)
, c’est que Réussite est optimal.8. En prenant la suite
σ = 3, 1, 2
on aura les deux piles : 13 2 et après avoir enlevé
1
les têtes de piles ne vont plus croissante.9. Une fois que la carte du dessus de
T [0]
est enlevée les têtes des pilesT [1]
, . . . ,T [p]
sont toujours croissantes mais la tête deT [0]
n’a plus forcément une valeur inférieur à celle de la tête deT [1]
. Il faut alors procéder par insertion deT [0]
dans la suite du tableau de manière à retrouver la propriété.10. Code :
void rassembler(pile_t T[], int nb_piles, elements_t res[], int nb_elts){
int i; /* indice de res (le tableau résultant) */
int j; /* indice de T (le tableau de piles) */
int k = 0; /* indice dans T de la première pile non vide */
for (i = 0; i < nb_elts; i++) {
res[i] = depiler(T[k]); /* On récupère le plus petit élément. */
if ( estvide(T[k]) ) { /* Pile vide: passer à la suivante. */
k++;
}
else { /* Sinon on doit reclasser les piles. */
j = k;
} } }