Licence MPI, Semestre 1, Introduction `a l`informatique (Info 111
Transcription
Licence MPI, Semestre 1, Introduction `a l`informatique (Info 111
Licence MPI, Semestre 1, Introduction à l’informatique (Info 111) Année 2015–2016 TD 5 : Fonctions et tableaux Exercice 1. On considère le programme suivant : #include <i o s t r e a m > #include <v e c t o r > using namespace s t d ; int mystere ( v e c t o r <int> t ) { int m = t [ 0 ] ; f o r ( int i = 1 ; i < t . s i z e ( ) ; i++ ) { if ( m < t [ i ] ) m = t[i]; } return m ; } int main ( ) { v e c t o r <int> t = { 5 , −1, 3 , 7 , −4, 8 , 4 } ; c o u t << mystere ( t ) << e n d l ; return 0 ; } (1) Exécuter pas à pas ce programme, que fait-il ? Que fait la fonction mystere ? Correction Ce programme affiche 8. La fonction mystère calcule le maximum du tableau. (2) Modifier le programme pour qu’il affiche le minimum et le maximum d’un tableau. Correction #include <i o s t r e a m > #include <v e c t o r > using namespace s t d ; /∗ ∗ Renvoie l ’ é l é ment l e p l u s grand du t a b l e a u ∗ ∗/ int max( v e c t o r <int> t ) { int m = t [ 0 ] ; f o r ( int i = 1 ; i < t . s i z e ( ) ; i++ ) { if ( t [ i ] > m ) m = t[i]; } return m ; } /∗ ∗ Renvoie l ’ é l é ment l e p l u s p e t i t du t a b l e a u ∗ ∗/ int min ( v e c t o r <int> t ) { int m = t [ 0 ] ; f o r ( int i = 1 ; i < t . s i z e ( ) ; i++ ) { if ( t [ i ] < m ) m = t[i]; } return m ; 1 2 TD 5 : FONCTIONS ET TABLEAUX } int main ( ) { v e c t o r <int> tab = { 5 , −1, 3 , 7 , −4, 8 , 4 } ; c o u t << ”Le max e s t ”<< max( tab ) <<e n d l ; c o u t << ”Le min e s t ”<< min ( tab ) <<e n d l ; return 0 ; } Exercice 2. Quelques fonctions sur les tableaux : (1) Spécifier et écrire une fonction qui affiche les éléments d’un tableau. Correction /∗ ∗ A f f i c h e un t a b l e a u ∗ @param t a b un t a b l e a u d ’ e n t i e r s ∗ ∗/ void a f f i c h e T a b l e a u ( v e c t o r <int> tab ) { f o r ( int i =0 ; i <tab . s i z e ( ) ; i ++) { cout<<tab [ i ]<< ’ \ t ’ ; } cout<<e n d l ; } (2) Spécifier et écrire une fonction qui teste si deux tableaux sont égaux. Correction /∗ ∗ T e s t e s i deux t a b l e a u x s o n t é gaux ( t a i l l e s é g a l e s , é l é ments de même i n d i c e é gaux ) ∗ @param t a b 1 l e p r e m i e r t a b l e a u d ’ e n t i e r s ∗ @param t a b 2 l e d e u x i ème t a b l e a u d ’ e n t i e r s ∗ @return v r a i s i l e s deux t a b l e a u x s o n t é gaux , f a u x s i n o n ∗ ∗/ bool t e s t E g a u x ( v e c t o r <int> tab1 , v e c t o r <int> tab2 ) { int t a i l l e = tab1 . s i z e ( ) ; i f ( tab2 . s i z e ( ) != t a i l l e ) { return f a l s e ; } else { f o r ( int i =0 ; i < t a i l l e ; i ++) { i f ( tab1 [ i ] != tab2 [ i ] ) { return f a l s e ; } } return true ; } } (3) Spécifier et écrire une fonction qui compte le nombre d’éléments plus grands que 10 dans un tableau d’entiers. Correction /∗ ∗ Compte l e nombre d ’ é l é ments p l u s g r a n d s que 10 dans l e t a b l e a u ∗ @param t a b un t a b l e a u d ’ e n t i e r ∗ @return nombre d ’ é l é ments p l u s grand que 10 ∗/ TD 5 : FONCTIONS ET TABLEAUX 3 int plusGrandQueDix ( v e c t o r <int> tab ) { int r e s = 0 ; f o r ( int i =0 ; i <tab . s i z e ( ) ; i ++) { i f ( tab [ i ] > 1 0 ) res = res + 1 ; } return r e s ; } (4) Spécifier et écrire une fonction qui renvoie vrai si un tableau d’entiers est trié dans l’ordre croissant, et faux sinon. Correction /∗ ∗ T e s t e s i un t a b l e a u e s t t r i é en o r d r e c r o i s s a n t ∗ @param t a b un t a b l e a u d ’ e n t i e r ∗ @return t r u e s i l e t a b l e a u e s t t r i é en o r d r e c r o i s s a n t , f a l s e s i n o n ∗/ bool e s t T r i e ( v e c t o r <int> tab ) { f o r ( int i =0 ; i <tab . s i z e () −1 ; i ++) { i f ( tab [ i ] > tab [ i +1]) return f a l s e ; } return true ; } Exercice 3. On rappelle que la suite de Fibonacci est définie récursivement par la relation : Un = Un−1 + Un−2 . Cette définition doit être complétée par une condition d’initialisation, en l’occurrence : U1 = U2 = 1. Introduite par Léonard de Pise (surnommé Fibonacci), cette suite décrit l’évolution d’un modèle simple de population de lapins. Les premiers termes sont donnés par : 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, ... Voir aussi http://oeis.org/A000045. 4 TD 5 : FONCTIONS ET TABLEAUX L’objectif est d’implanter la fonction dont la documentation et les tests sont donnés ci-dessous : /∗ ∗ S u i t e de F i b o n a c c i ∗ @param n un e n t i e r s t r i c t e m e n t p o s i t i f ∗ @return l e n−i ème terme de l a s u i t e de F i b o n a c c i ∗ ∗/ int f i b o n a c c i ( int n ) { // À f a i r e : É c r i r e l e code i c i ! } void f i b o n a c c i T e s t ( ) { ASSERT( f i b o n a c c i ( 1 ) ASSERT( f i b o n a c c i ( 2 ) ASSERT( f i b o n a c c i ( 3 ) ASSERT( f i b o n a c c i ( 4 ) ASSERT( f i b o n a c c i ( 5 ) ASSERT( f i b o n a c c i ( 6 ) } == == == == == == 1 1 2 4 5 8 ); ); ); ); ); ); (1) Vérifier que les tests sont cohérents avec la documentation. Corriger si nécessaire. Correction ASSERT( f i b o n a c c i T a b l e a u ( 4 ) == 3 ) ; (2) Première implantation : en utilisant une boucle for et un tableau de taille n pour stocker tous les éléments de la suite U1 , . . . , Un . Correction int f i b o n a c c i T a b l e a u ( int n ) { i f ( n == 1 or n == 2 ) { return 1 ; } else { v e c t o r <int> u ( n ) ; u[0] = 1 ; u[1] = 1 ; f o r ( int i = 2 ; i < n ; i ++) { u [ i ] = u [ i −1] + u [ i −2] ; } return u [ n −1] ; } } (3) Deuxième implantation : en utilisant une boucle for et trois variables dont deux qui, au début de chaque tour de boucle, contiennent les valeurs de Uk−1 et Uk−2 . Correction int f i b o n a c c i V a r i a b l e s ( int n ) { int u1 = 1 ; int u2 = 1 ; int tmp = 0 ; i f ( n == 1 or n == 2 ) { return 1 ; } else { f o r ( int i = 3 ; i <= n ; i ++) { tmp = u2 ; u2 = u1 + u2 ; u1 = tmp ; TD 5 : FONCTIONS ET TABLEAUX 5 } return u2 ; } } (4) Troisième implantation : en utilisant une fonction récursive, c’est-à-dire qui s’appelle elle même. Correction int f i b o n a c c i R e c u r s i v e ( int n ) { i f ( n == 1 or n == 2 ) { return 1 ; } else { return f i b o n a c c i R e c u r s i v e ( n−2) + f i b o n a c c i R e c u r s i v e ( n−1) ; } } (5) Laquelle de ces trois implantations est la plus expressive ? Correction La fonction récursive : elle correspond à la définition mathématique de la suite. (6) ♣ Comparer l’efficacité des trois implantations. Quel phénomène a lieu pour la fonction récursive ? Comment pourrait-on le corriger ? Exercice ♣ 4. (1) Que fait la fonction suivante ? v e c t o r <int> mystere ( v e c t o r <int> t ) { int n = t . s i z e ( ) ; v e c t o r <int> r ( n ) ; f o r ( int i =0 ; i <n ; i ++) r [ i ] = t [ n−1− i ] ; return r ; } (2) Un palindrome est un tableau qui peut se lire de la même façon dans les deux sens. Par exemple le tableau {2, 8, −1, 6, −1, 8, 2} est un palindrome. Écrire une fonction qui teste si un tableau est un palindrome en utilisant les fonctions déjà vues dans le TD. (3) Écrire une fonction palindrome indépendamment des exercices précédents. (4) Commenter les avantages et inconvénients de chacune. Correction bool p a l i n d r o m e ( v e c t o r <int> t ) { return t e s t E g a u x ( t , m i r r o r ( t ) ) ; } bool p a l i n d r o m e I n d e p e n d a n t ( v e c t o r <int> t ) { int n = t . s i z e ( ) ; f o r ( int i = 0 ; i < n /2 ; i ++) { i f ( t [ i ] != t [ n−i −1]) return f a l s e ; 6 TD 5 : FONCTIONS ET TABLEAUX } return true ; } void p a l i n d r o m e T e s t ( ) { ASSERT ( palindrome ({ ASSERT ( palindrome ({ ASSERT ( not p a l i n d r o m e ( { ASSERT ( not p a l i n d r o m e ( { ASSERT ( not p a l i n d r o m e ( { } 1 ,2 ,3 ,4 ,5 ,4 ,3 ,2 ,1 1 ,2 ,3 ,4 ,4 ,3 ,2 ,1 1 ,2 ,3 ,4 ,4 ,3 ,2 ,0 1 ,2 ,3 ,4 ,5 ,3 ,3 ,2 ,1 1 ,2 ,3 ,4 ,3 ,3 ,2 ,1 }) }) }) }) }) ); ); ); ); ); int main ( ) { palindromeTest ( ) ; return 0 ; } La première est plus concise et expressive (proche de la définition mathématique). La deuxième est plus optimisée.