Vous êtes sur la page 1sur 2

Université Pierre et Marie Curie Master M1 "Mathématiques et Applications"

Période 2 - 2010/2011 Programmation en C/C++


Examen du 04 mai 2011
Deux heures - Sans document.

Exercice 1 (Questions de cours)


1. A quoi correspondent les symboles >> et << en C++.
2. Ecrire précisément le prototype des fonctions permettants de modifier le comportement de ces symboles. Indiquer
le(s) fichier(s) d’en-tête(s) à inclure.

3. Ecrire une unique fonction générique permettant d’afficher aussi bien des objets de la classe std::vector<int>
que de la classe std::vector<double>. Préciser le fichier d’en-tête à inclure.

4. Ecrire une unique fonction générique permettant d’afficher aussi bien des objets de la classe std::vector<int>
que de la classe std::list<int>. Préciser les fichiers d’en-têtes à inclure.

Exercice 2 (Tri bulle en C)


Le principe du tri bulle (bubble sort) est de comparer deux à deux les éléments e1 et e2 consécutifs d’une
structure de données (tableau, liste chaînée...) et d’effecteur une permutation si e1 > e2 . On continue de trier
jusqu’à ce qu’il n’y ait plus de permutation. Voici un pseudo-code de l’algorithme du tri bulle :
fonction tri_bulle ( tableau T , entier n )
2 repeter
en_desordre = faux
4 pour j parcourant les indices du tableau jusqu ’a l ’ avant dernier
si T [ j ] > T [ j +1] , alors
6 echanger T [ j ] et T [ j +1]
en_desordre = vrai
8 tant que en_desordre = vrai

1. Ecrire, en faisant attention à la syntaxe, une fonction tri_bulle en C qui code cet algorithme.

On peut prouver qu’après la k-ème étape de l’algorithme (c’est à dire après le k-ème passage dans la boucle
repeter... tant que) les k derniers éléments du tableau sont à leur place. Vous pouvez vous en convaincre
aisément par une petite récurrence.
2. Ecrire une fonction tri_bulle_opt qui implémente une version « optimisée » de l’algorithme du tri bulle en
tenant compte de la remarque précédente.

3. Ecrire un très court programme en C qui


– demande un entier n à l’utilisateur
– crée un tableau dynamique d’entiers tab de taille n
– initialise le tableau par des valeurs entières pseudo-aléatoires (fonction random())
– trie le tableau avec la fonction tri_bulle_opt.

On souhaite maintenant appliquer cet algorithme de tri à une autre structure de données : une liste doublement
chaînée, c’est à dire permettant de se déplacer à l’aide de pointeurs vers l’élément suivant (s’il existe) ainsi que
vers l’élément précédent (s’il existe).
4. Définir le type récursif struct maillon à utiliser pour coder une liste doublement chaînée d’entiers.

5. Ecrire une fonction swap qui échange deux maillons consécutifs de la chaîne, c’est à dire une fonction dont le
prototype est
void swap ( struct maillon * m );
qui échange le maillon m et celui qui suit (on suppose que m n’est pas le dernier maillon de la liste).

6. En déduire le code d’une fonction tri_bulle_opt_liste qui trie une liste doublement chaînée en utilisant l’al-
gorithme du tri bulle « optimisé ».

1
Exercice 3 (Algorithme numérique en C++)
Soit l’objet fonctionnel (ou foncteur) abstrait FctR suivant
struct FctR {
2 virtual double operator ()( double ) const = 0;
virtual double derivee ( double ) const = 0;
4 };
qui permet de manipuler aisément les fonctions réelles.
1. Comment sont qualifiées les méthodes operator() et derivee ? Pourquoi ?
2. Ecrire une classe Cubique héritée de FctR qui code les fonctions de la forme
f (x) = (ax + b)3 , a ∈ R, b ∈ R.

Pour un argument x donné, l’opérateur operator() doit renvoyer f (x) et la méthode derivee doit renvoyer f 0 (x).
Les paramètres a et b seront des champs privés de la classe.
On considère maintenant la classe abstraite AlgorithmeR suivante qui permettra une implémentation des algo-
rithmes numériques de la forme xn+1 = g(n, xn ) où g est une fonction codant l’algorithme dépendant d’une
fonction f donnée.
class AlgorithmeR {
2 public :
AlgorithmeR ( double valeur_init , FctR & f )
4 : x_n ( valeur_init ) , n_iter (0) , _______ {};
AlgorithmeR & operator ++() {
6 calcul_iter ();
++ n_iter ;
8 return _______ ;
};
10 _______
virtual void calcul_iter () = 0;
12 double x_n ;
int n_iter ;
14 FctR & fct ;
};
Les champs sont les suivants :
– x_n : code la valeur de l’algorithme à l’instant n
– n_iter : code la valeur de l’instant i.e n
– fct : est une référence sur un objet fonctionnel d’une classe héritée de FctR
– calcul_iter() : méthode, redéfinie dans les classes filles, codant l’algorithme, i.e. la fonction g.
3. Compléter le code de la classe AlgorithmeR (vous pouvez juste indiquer le numéro de la ligne et l’instruction).
Est-il nécessaire que fct soit une référence ?
On se propose de tester cette classe abstraite en écrivant une classe Newton dérivée de AlgorithmeR qui code
l’algorithme de Newton pour la recherche d’un zéro d’une fonction (réelle) i.e.
f (xn )
∀n ≥ 0, xn+1 = xn − , x0 ∈ R.
f 0 (xn )
On considère l’extrait de code suivant qui affiche les 30 premières itérations de l’algorithme de Newton appliqué
à la fonction f (x) = (−3.5x + 5.5)3 avec la condition initiale x0 = 5.1.
Cubique F ( -3.5 , 5.5); // ie a = -3.5 et b = 5.5
2 Newton N (5.1 , F ); // ie x_0 = 5.1
for ( int i = 0; i <= 30; ++ i ) {
4 cout << N << endl ;
++ N ;
6 }
4. Ecrire la classe Newton qui permet de reproduire cet exemple.
Si on remplace la dérivée de la fonction dans la méthode de Newton avec une différence finie on obtient la
méthode de la sécante. Elle est définie par la relation récurrente
xn − xn−1
∀n ≥ 0, xn+1 = xn − f (xn ), x0 ∈ R
f (xn ) − f (xn−1 )
où on pose x−1 = x0 − 1.
5. Ecrire une classe Secante dérivée de AlgorithmeR qui permet d’implémenter cet algorithme.

Vous aimerez peut-être aussi