Algorithmique et structure de données Cours de Robert Cori – 1`ere

publicité
Algorithmique et structure de données
Cours de Robert Cori – 1ère Année ENSEIRB
TD 2
1
Algorithmes récursifs simples
1. Écrire une version récursive de l’algorithme permettant de calculer rapidement
la puissance n-ième d’un nombre entier.
Correction 1
int puissance(int a, int n) // Version explicite
{
if (n == 1) { return a; }
else if (n % 2 == 0)
{ return puissance(a, n / 2) * puissance(a, n / 2); }
else
{ return puissance(a, n / 2) * puissance(a, n / 2) * a; }
}
int puissance(int a, int n) // Version optimisée
{
int p;
if (n == 1) { p = a; }
else {
p = puissance(a, n / 2);
p = p * p;
if (n % 2 == 1) { p = p * a; }
}
return p;
}
2. Sachant que le calcul du produit de deux entiers de 1000 chiffres prend 1/100
de seconde, calculer le temps mis pour calculer a1000000 , où a est un entier de
1000 chiffres, par cette méthode. Comparer ce temps à celui que prendrait
un algorithme consistant à effecetuer 1000000 de multiplications (noter que
log2 (1000000) ≈ 20).
3. Le plus grand commun diviseur, ou PGCD, de deux entiers non nuls est le plus
grand nombre entier qui divise ces deux nombres. Par exemple, le PGCD de 1071
1
et 1029 est 21. Écrire un algorithme récursif calculant le PGCD de deux entiers,
en s’inspirant de l’algorithme itératif donné en cours.
Correction 2 On considère a > b. Il faut démontrer que tout nombre qui divise
a et b divise aussi le reste de la division de a par b, ce qui se voit facilement
avec a = bq + r. Réciproquement, tout nombre qui divise b et r divise ausi a.
Donc pgcd(a, b) = pgcd(b, r).
int pgcd(int a, int b)
{
if (b == 0) { return a; }
else { return pgcd(b, a % b); }
}
2
Figure de Sierpiński
La figure de Sierpiński est une figure géométrique d’aire nulle et de périmètre infini.
Elle se construit, à partir d’un triangle équilatéral, par subdivisions successives. On la
définit de la façon suivante :
– La figure de Sierpiński d’ordre 1 est un triangle équilatéral noir,
– La figure de Sierpiński d’ordre n est obtenue à partir de celle d’ordre n − 1 en
inscrivant un triangle équilatéral blanc à l’intérieur de tous les triangles noirs,
formant ainsi trois nouveaux triangles noirs à l’intérieur de chacun de ces triangles.
Voici par exemple les figures de Sierpiński d’ordre 1, 2, 3, 4 et 5 :
1. Écrire un algorithme récursif dessinant la figure de Sierpiński d’ordre n dont le
sommet du sud-ouest du triangle a pour coordonnées (x, y) et dont la longueur
du coté est a :
void sierpinski(x, y, a, n)
On utilisera pour cela la fonction
tracer_ligne(x, y, a, b)
qui trace un segment entre les points de coordonnées (x, y) et (a, b). On remarquera aussi que la figure de Sierpiński d’ordre n > 1 est formée de trois figures
plus petites d’ordre n − 1.
2
Correction 3 → Préciser qu’on dessine les triangles noirs, pas les blancs !
void sierpinski(x,
{
if (n == 1) {
tracer_ligne(
tracer_ligne(
tracer_ligne(x
}
else {
sierpinski(
sierpinski(x +
sierpinski(x +
}
}
3
y, a, n)
x, y, (x + a) / 2, y + a * sqrt(3) / 2);
x, y,
x + a,
y);
+ a, y, (x + a) / 2, y + a * sqrt(3) / 2);
x,
y, a / 2, n - 1);
a / 2,
y, a / 2, n - 1);
a / 4, y + a * sqrt(3) / 4, a / 2, n - 1);
Tris
1. Le tri à bulles consiste à faire remonter le plus grand élément d’un tableau
jusqu’à la fin de celui-ci (comme une bulle d’air remonte à la surface). Pour cela,
on parcourt le tableau, en triant les éléments successifs deux à deux, autant de
fois que nécessaire. Écrire un algorithme effectuant le tri à bulles.
Correction 4
void tri_a_bulles(int tab[], int taille)
{
int fin = taille - 1;
bool echange = true;
while(echange) {
echange = false;
for (i = 0; i < fin; i++) {
if (tab[i] > tab[i + 1]) {
echanger(tab[i], tab[i + 1]);
echange = true;
}
}
fin--;
}
}
2. Le tri par insertion consiste à insérer successivement chaque élément dans une
partie triée dont la taille augmente à chaque étape. Pour insérer un élément on
décale les éléments du tableau pour insérer cet élément à sa place dans la partie
déjà triée. Écrire un algorithme effectuant le tri par insertion.
3
Correction 5
void tri_insertion(int tab[], int taille)
{
for (i = 1; i < taille; i++) {
int m = tab[i];
int k = i;
while (k > 0 && tab[k - 1] > m) {
tab[k] = tab[k - 1];
k--;
}
tab[k] = m;
}
}
4
Téléchargement