• Aucun résultat trouvé

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 en

log N

. L’empreinte mémoire est donc de l’ordre de

log N

ce qui est donc mieux que d’être de l’ordre de

N

.

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

puisque

1

peut être posé n’importe où (deux destinations possibles. Et un seul déplacement à partir d’un des autres piquet : si

d

et

d

sont les deux disques aux sommet des deux autres piquets avec

d < d

alors

d

ne peut pas être posé sur

1

ou sur

d

, et

d

peut seulement être posé sur

d

. Deux même si l’une des autres piles est vide (c’est comme si

d

é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 a

2

n

1

déplacements,

1

est déplacé exactement

2

n−1fois.

6. Soit

1

occupe tour à tour

a, b, c, a, b, c, a, b, c, . . .

Soit

1

occupe tour à tour

a, c, b, a, c, b, a, c, b, . . .

7. La séquence des positions de

1

doit se terminer sur

c

. Dans les deux séquences précédentes, la position

a

correspond à un nombre de déplacements divisible par

3

(

0

déplacement pour la première position). S’il y a

k

déplacements de

1

, dans la séquence

a, b, c, a, b, c, . . .

(respec-tivement

a, c, b, a, c, b, . . .

) on doit avoir

k mod 3 = 2

(respectivement

k mod 3 = 1

), pour atterrir sur le piquet

c

. Or il y a

2

n−1déplacements du disque

1

. Reste donc à déterminer le reste modulo

3

de

2

n−1en fonction de

n

pour savoir quelle séquence de déplacement choisir.

Ce reste n’est jamais nul (c’est cohérent). Il peut être

1

(pour

n = 1

) ou

2

(pour

n = 2

), et en remultipliant par deux pour passer à chaque fois au

n

suivant, on obtient

4 = 1 mod 3

(

n

vaut

3

), et on tombe sur un cycle (

1

×

2 = 2

,

2

×

2 = 4 = 1 mod 3

etc) . Pour

n

pair il faut donc choisir la séquence

a, b, c, . . .

et pour

n

impair la séquence

a, c, b, . . .

8. On est dans le cas

n

pair donc

1

se déplace selon la séquence de positons

a, b, c, . . .

. Le déplacement qui vient d’être fait ne portait pas sur

1

, on doit donc déplacer

1

.

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 valeur

inférieure à

x

et de poser la carte

x

sur la pile suivante. Pour chercher cette pile, on cherche par dichotomie

x

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 plus

N

piles, insérer une carte prend

O(log N )

comparaisons. Donc insérer

N

cartes prend

O(N log N )

comparaisons.

3. On remarque que si

x

vient d’être placé sur une pile

T [j]

alors toute carte

y

qui suit

x

dans

σ

et qui est plus grande que

x

doit être placée après la pile

T [j]

. En effet au moment de placer

x

, toutes les piles avant

T [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 placer

y

, il n’est pas possible de le poser sur une des piles avant

T [j + 1]

. Supposons que

a

1

< . . . < a

k est une sous-suite de

σ

. Une fois que

a

iest placé sur une pile,

a

i+1est nécessairement placé sur une des piles suivantes. Il faut donc au moins

k

piles.

4.

5. Si il y a une flêche d’un élément

x

vers élément

y

alors l’élément

x

est plus grand que l’élément

y

et

x

a été posé après

y

. 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 longueur

p

.

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 que

p

minore

l(σ)

. 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 moins

l(σ)

piles et que Réussite en forme exactement

l(σ)

, c’est que Réussite est optimal.

8. En prenant la suite

σ = 3, 1, 2

on aura les deux piles : 1

3 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 piles

T [1]

, . . . ,

T [p]

sont toujours croissantes mais la tête de

T [0]

n’a plus forcément une valeur inférieur à celle de la tête de

T [1]

. Il faut alors procéder par insertion de

T [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;

} } }

Documents relatifs