Variables indicées et tableaux Structure de tableau Pour désigner une séquence d’éléments de même type Pour représenter des vecteurs/n-tuples d’éléments de type T (occupant s cellules) Notation habituelle : Représentation immédiate : séquence contigüe de Ts v1, v 2, v3, …, v n adresses contenus On parle de vecteur a K1 point dans l’espace : (6, 5, –2) a+s K2 prix moyen du carburant à chaque trimestre : (1.29, 1.34, 1.31, 1.28) a + 2s K3 a + (n-1)s Kn Exemples Autres exemples : __ G. Falquet, CUI, Université de Genève 1 de 23 G. Falquet, CUI, Université de Genève Utilisation des tableaux 2 de 23 Opérations globales sur les tableaux Sélection d’un élément : Affectation globale V ← (e1, e2, …, en) x ← t[k] équivalent à V[1] ← e1, V[2] ← e2, … V←W Affectation d’une valeur à un élément (l’ancienne est effacée) équivalent à V[1] ← W[1], V[2] ← W[2], … t[k] ← e Temps d’exécution proportionnel à la taille de V. Affectation de tranches V[i…j] ← (e0, …, er) équivalent à V[i] ← e0, V[i+1] ← e1, …, V[j] ← er r=i-j G. Falquet, CUI, Université de Genève 3 de 23 G. Falquet, CUI, Université de Genève 4 de 23 Un exemple: vérification de date Le même avec un tableau Problème: écrire un algorithme qui vérifie si une date (jour, mois, année) est correcte On crée un tableau des nombres de jours. . nbJours[1..12] ← (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) fonction booléenne vérifDate(j, m, a) si (j < 1 ou m < 1 ou m > 12) retourne faux bisextile ← a modulo 4= 0 // correct entre 2000 et 2099) Qu’on utilise dans la fonction si m = 1 retourne j ≤ 31 si m = 2 et bisextile retourne j ≤ 29 fonction booléenne vérifDate(j, m, a) si m = 2 et non bisextile retourne j ≤ 28 si (j < 1 ou m < 1 ou m > 12) retourne faux si m = 3 retourne j ≤ 31 si (a modulo 4= 0) nbJours[2] = 29 sinon nbJours[2] = 28 ... retourne j ≤ nbJours[m] si m = 12 retourne j ≤ 31 retourne faux G. Falquet, CUI, Université de Genève 5 de 23 G. Falquet, CUI, Université de Genève 6 de 23 Tableau ≠ Ensemble ! En Java class GestionDates { Ordre static int[ ] nbJours = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; ensembles : {a, c, g} = {g, c, a} tableaux : (a, r, g) ≠ (r, g, a) static boolean verifDate(int j, int m, int a) { Accès if (j < 1 || m < 1 || m > 12) return false; tableaux : 1er élément, 2e, 3e, etc. if (a % 4 == 0) nbJours[ 2 ] = 29 ensembles : --- else nbJours[ 2 ] = 28; Nb d’occurences return j <= nbJours[ m ] ensembles : {a, c, a, b, a} = {a, c, b} } tableaux : (a, a, a, a) ≠ (a) } Opérations ensembles : union, intersection, différence tableau : affectation d’une valeur à un élément G. Falquet, CUI, Université de Genève 7 de 23 G. Falquet, CUI, Université de Genève 8 de 23 Micro algorithme - Appliquer une fonction Micro algorithmes - Collecter On a On a A : tableau[1..n] de T; A : tableau[1..n] de T; op : opération associative sur T f : fonction de T dans T A = (v1, v2, …, vn) A = (v1, v2, …, vn) On veut r = v1 op v2 op v3 … op vn On veut A’ = (f(v1), f(v2), …, f(vn)) r ← neutre de l’opération pour i de 1 à n { pour i de 1 à n { A[ i ] ← f(A[ i ]) r ← r op A[ i ] } } Exemple Exemple pour i de 1 à n { salaire[ i ] ← 1.34 * salaire[ i ] } total ← 0 pour i de 1 à n { total ← total + salaire[ i ] } G. Falquet, CUI, Université de Genève 9 de 23 G. Falquet, CUI, Université de Genève Exemple : le crible d’Eratosthène 10 de 23 Pseudo-algorithme Pour trouver tous les nombres premiers de 2 à n (encore !) Faire une liste des nombres faire une liste des nombres de 2 à n Barrer tous les multiples de 2 supérieurs à 2 p <-- 2 Barrer tous les multiples de 3 supérieurs à 3 tant que ( p * p ≤ n) { 4 est déjà barré barrer tous les multiples de p Barrer tous les multiples de 5 supérieurs à 5 p <-- le plus petit nombre non barré supérieur à p 6 est déjà barré } Barrer tous les multiples de 7 supérieurs à 7 8 est déjà barré Remarque 9 est déjà barré Tout nombre < n qui n’est pas premier est multiple d’un nombre inférieur à 10 est déjà barré n. Donc on peut arrêter l’algorithme quand p * p > n. Barrer tous les multiples de 11 supérieurs à 11 etc. Les nombres qui restent sont premiers (ils ne sont multiples de personne) G. Falquet, CUI, Université de Genève 11 de 23 G. Falquet, CUI, Université de Genève 12 de 23 Structure de données : tableau de booléens Algorithme avec un tableau de booléens au début f v v v v v v v v v v v v v v v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pour i de 2 à n { Barré[ i ] <-- faux } v p <-- 2 max <-- racine carrée de n tant que ( p ≤ max) { barrer les multiples de 2 f v v f v f v f v f v f v f v f 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 si ( non Barré [p] ) { v // Barrer les multiples de p i <-- p + p tant que i ≤ n { Barré[ i ] <-- vrai ; i <-- i + p } puis ceux de 3 f v v f v f v f f f v f v f f f 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } v p <-- p + 1 } etc. G. Falquet, CUI, Université de Genève 13 de 23 G. Falquet, CUI, Université de Genève Complexité en temps Le calcul de la complexité … est complexe √n fois nb opérations [ ] = n/2 + n/3 + n/5 + n/7 + n/11 + … + n/pk – π (√n} tant que ( p ≤ max) { π (√n) fois (pk = plus grand nombre premier inférieur à √n) si ( non Barré [p] ) { On sait i <-- p + p tant que i ≤ n { Barré[ i ] <-- vrai ; i <-- i + p } n / p – 1 fois 14 de 23 1/p1 + 1/p 2 + 1/p3 + … + 1/pk ~= log(log(k)) } Mais que vaut k ? p <-- p + 1 Combien y a-t-il de nombres premiers inférieurs à √n ? } Legendre a trouvé : π (x) ~= x / (log(x) – 1.0836) (Legendre) π(x) = nombre de nb. premiers inférieurs à x Donc nb. opérations ~= n log(log(√n / (log(√n – 1.08)) nb opérations [ ] = n/2 + n/3 + n/5 + n/7 + n/11 + … + n/pk – π (√n} = n log(log(√n)) – n log(log(log(√n – 1.08))) ∈ O(n log(log(√n))) (pk = plus grand nombre premier inférieur à √n) G. Falquet, CUI, Université de Genève 15 de 23 G. Falquet, CUI, Université de Genève 16 de 23 Accès associatif / recherche Algorithmes 1 But : trouver une valeur dans un tableau T Le meilleur algorithme : regarder successivement dans T[0], T[1], … etc. T un tableau indicé de 0 à n-1 résultat = 1ère position de x dans T Complexité : O(taille de T) résultat = -1 si x n’est pas dans T fonction entière recherche (x, T) { Tout algorithme basé sur l’accès associatif est inefficace i←0 (à moins d’avoir beaucoup de processeurs en parallèle) tant que ( i < n et T[ i ] ≠ x ) i ← i + 1 si i = n retourne –1 sinon retourne i } Cet algorithme est faux. G. Falquet, CUI, Université de Genève 17 de 23 G. Falquet, CUI, Université de Genève Algorithmes 2 18 de 23 Algorithmes 3 T un tableau indicé de 0 à n-1 T un tableau indicé de 0 à n-1 résultat = 1ère position de x dans T résultat = 1ère position de x dans T résultat = -1 si x n’est pas dans T résultat = -1 si x n’est pas dans T fonction entière recherche (x, T) { fonction entière recherche (x, T) { i←0 i←0 tant que ( i < n ) { tant que ( i < n et ensuite T[ i ] ≠ x ) i ← i + 1 si T[ i ] = x retourne i si i = n retourne –1 sinon retourne i sinon i ← i + 1 } } retourne –1 Utilise l’évaluation partielle des expressions booléennes. } G. Falquet, CUI, Université de Genève Opérateur && en Java. 19 de 23 G. Falquet, CUI, Université de Genève 20 de 23 Recherche dans un tableau trié Algorithme On cherche 6.25 Précondition : x est trié par ordre croissant des valeurs. Invariant : si x se trouve dans T, il est entre les positions inf et sup. sup fonction entière dichotomique(T, x) { inf <-- 0 ; sup <-- taille T – 1; tant que inf <= sup { millieu <-- (sup + inf) / 2 ; millieu 12.4 si (T[ millieu ] = x) retourner millieu 12.4 12.4 sup sup sinon etc. millieu inf millieu 3.5 sinon inf <-- millieu + 1 } 3.5 retourner -1 inf /* pas trouvé */ } inf G. Falquet, CUI, Université de Genève 21 de 23 Complexité Nombre d’itérations = si n = 2k au maximum k itérations (2k , 2k–1, 2k–2 , …, 8, 4, 2, 1) k = log2(n) Complexité : O(log2(n)) G. Falquet, CUI, Université de Genève si (T[ millieu ] > x) sup <-- millieu - 1 23 de 23 G. Falquet, CUI, Université de Genève 22 de 23