Exercice 1: Recherche dans un tableau CORRIGE T.D. 2

publicité
Université Paris Dauphine
DE MI2E - 1re année
Algorithmique et Programmation 2
2014-2015
CORRIGE T.D. 2
Exercice 1: Recherche dans un tableau
Soit T un tableau de n cellules contenant des valeurs numériques (dont certaines éventuellement identiques) et soit v une valeur numérique.
1. Ecrire un programme python qui renvoie le plus petit indice i tel que T [i] = v ou 0 s’il n’en existe
pas (le tableau est parcouru par indice croissant).
2. Donner la complexité de ce programme en fonction de n.
1. def plusPetitIndice (T, v):
for i in range (len (T)):
if T [i] == v:
return i
return -1
T = [1, 5, 0, 13, 3, 5, 7, 9]
print (plusPetitIndice (T, 13))
print (plusPetitIndice (T, 12))
En algorithmique :
PlusPetitIndice(T, n, v) : entier
Entrées : T un tableau, n sa dimension, v une valeur
Sorties : valeur du plus petit indice contenant v ou 0 s’il n’en
existe pas
Données : i:entier
pour i <- 1 à n faire
si v = T[i] alors
retourner i
finsi
finpour
retourner 0
2. Au pire cas : Time(n) ≤ (1 + 1)n + 1 = 2n + 1 d’où Time(n)∈ O(n).
Exercice 2: Recherche du plus grand indice
Soit T un tableau de n cellules contenant des valeurs numériques (dont certaines éventuellement identiques) et soit v une valeur numérique.
1. Ecrire un programme python qui renvoie le plus grand indice i tel que T [i] = v ou 0 s’il n’en
existe pas (le tableau est parcouru par indice croissant).
2. Donner la complexité de ce programme en fonction de n.
3. Quel est l’inconvénient de ce programme par rapport au précédent ?
4. La commande "pour indice ← valeur initiale à valeur finale faire" où valeur finale est inférieure
ou égale à valeur initiale réalise des boucles dont l’indice est décroissant. Utiliser cette commande
pour proposer un algorithme plus efficace "symétrique" de l’algorithme de la question 1.
1. def plusGrandIndice (T, v):
indice = -1
for i in range (len (T)):
if T [i] == v:
indice = i
return indice
T = [1, 5, 0, 13, 3, 5, 7, 9]
print (plusGrandIndice (T, 5))
print (plusGrandIndice (T, 12))
en algorithmique :
PlusGrandIndice(T, n, v) : entier
Entrées : T un tableau, n sa dimension, v une valeur
Sorties : valeur du plus grand indice contenant v ou 0 s’il n’en
existe pas
Données : i, indice: entiers
indice <- 0
pour i <- 1 à n faire
si v = T[i] alors
indice <- i
finsi
finpour
retourner indice
2. Au pire cas : Time(n) ≤ 1 + (1 + 1 + 1)n + 1 = 3n + 2 d’où Time(n)∈ O(n).
3. Nous sommes obligés de parcourir tout le tableau.
4. def plusGrandIndiceDecroissant (T, v):
i = len (T) - 1
while (i > -1):
if T [i] == v:
return i
i = i - 1
return -1
T = [1, 5, 0, 13, 3, 5, 7, 9]
print (plusGrandIndiceDecroissant (T, 5))
print (plusGrandIndiceDecroissant (T, 12))
en algorithmique :
PlusGrandIndice2(T, n, v) : entier
Entrées : T un tableau, n sa dimension, v une valeur
Sorties : valeur du plus grand indice contenant v ou 0 s’il n’en
existe pas
Données : i:entier
pour i <- n à 1 faire
si v = T[i] alors
retourner i
finsi
finpour
retourner 0
Exercice 3: Recherche dans un tableau trié
On suppose maintenant que le tableau T est trié.
1. Ecrire un programme python qui renvoie un indice i (quelconque) tel que T [i] = v ou -1 s’il n’en
existe pas. Le principe du programme est le suivant :
(a) Il calcule milieu = (n + 1)/2 et il compare v avec T [milieu]. S’il y a égalité, il renvoie
milieu.
(b) Sinon si v < T [milieu] et milieu > 1, il s’appelle récursivement avec pour entrée la partie
de T allant de 0 à milieu − 1 et renvoie le résultat de cet appel.
(c) Sinon si v > T [milieu] et milieu < n, il s’appelle récursivement avec pour entrée la partie
de T allant de milieu + 1 à n − 1 et renvoie le résultat de cet appel.
(d) Sinon il renvoie -1 (i.e., pas trouvé).
2. Modifier l’algorithme pour qu’il renvoie le plus petit indice comme dans la question 1.
1. def chercheTableauTrie (T, v, deb, fin):
milieu = (deb+fin)/2
if T [milieu] == v:
return milieu
elif (v > T [milieu] and milieu < len (T) - 1):
return chercheTableauTrie (T, v, milieu+1, fin)
elif (v < T [milieu] and milieu > 0):
return chercheTableauTrie (T, v, deb, milieu-1)
else:
return -1
T = [1, 2, 3, 4, 5, 6, 7, 8,
print(chercheTableauTrie (T,
print(chercheTableauTrie (T,
print(chercheTableauTrie (T,
9, 10]
7, 0, len (T) - 1))
10, 0, len (T) - 1))
12, 0, len (T) - 1))
en algorithmique :
Cherche_tableau_trie(T, v, deb, fin) : entier
Entrées : T un tableau trié, v une valeur, deb une borne inf, fin
une borne sup
Sorties : valeur d’un indice contenant v ou 0 s’il n’en
existe pas
Données : milieu: entier
milieu <- (deb+fin)/2
si T[milieu] = v alors
retourner milieu
sinon si v > T[milieu] et milieu < n alors
retourner Cherche_tableau_trie(T, v, milieu+1, fin)
sinon si v < T[milieu] et milieu > 1 alors
retourner Cherche_tableau_trie(T, v, deb, milieu-1)
sinon
retourner 0
finsi
2. def chercheTableauTriePPI (T, v, deb, fin):
milieu = (deb + fin)/2
print (milieu, deb, fin)
if T [milieu] == v:
while T [milieu] == v and milieu > -1:
milieu = milieu - 1
return milieu + 1
elif (v > T [milieu] and milieu < len (T) - 1):
return chercheTableauTriePPI (T, v, milieu+1, fin)
elif (v < T [milieu] and milieu > 0):
return chercheTableauTriePPI (T, v, deb, milieu-1)
else:
return -1
T = [1, 2, 3, 4, 5, 6, 7, 7, 7,
print(chercheTableauTriePPI (T,
print(chercheTableauTriePPI (T,
print(chercheTableauTriePPI (T,
7, 7, 8, 9, 10]
7, 0, len (T) - 1))
10, 0, len (T) - 1))
12, 0, len (T) - 1))
Exercice 4: Complexité de la recherche dans un tableau trié
On étudie la complexité du dernier algorithme.
1. Démontrer que lorsque l’algorithme s’appelle récursivement, la taille du nouveau tableau est inférieure ou égale à n/2.
2. Soit T ime(n), le pire temps d’exécution de cet algorithme pour un tableau de taille inférieure ou
égale à n. En déduire que pour une constante c bien choisie :
T ime(1) ≤ c
∀n ≥ 2, T ime(n) ≤ c + T ime(n/2)
3. Démontrer par récurrence que T ime(n) ≤ c(log2 (n)+1) et donc que la complexité de l’algorithme
est en O(log2 (n)).
1. Taille du tableau gauche : milieu − 1 =
Taille du tableau droit : n − milieu = n
n+1
2 −
− n+1
2
1=
=
n−1
n
2 ≤ 2
n−1
n
2 ≤ 2
2. Pour n = 1, Time(n) ≤ 13. Au pire cas, on exécute les 13 opérations suivantes :
1er appel:
1 - milieu <- (deb+fin)/2
2 - si T[milieu] = v alors
3 - si v > T[milieu] et
4 - milieu < n alors
5 - sinon si v < T[milieu] et
6 - milieu > 1 alors
2ème appel:
1 - milieu <- (deb+fin)/2
2 - si T[milieu] = v alors
3 - si v > T[milieu] et
4 - milieu < n alors
5 - sinon si v < T[milieu] et
6 - milieu > 1 alors
7 - retourner 0
Pour n ≥ 2, Time(n) ≤ 13+ Time( n2 ). Au pire cas, on effectue les opérations suivantes :
1
2
3
4
5
6
7
-
milieu <- (deb+fin)/2
si T[milieu] = v alors
si v > T[milieu] et
milieu < n alors
sinon si v < T[milieu] et
milieu > 1 alors
retourner Cherche_tableau_trie_PPI(T, v, deb, milieu-1)
auquel s’ajoute le temps de calcul d’un appel récursif sur un tableau de taille
n
2
(cf. question 1).
3. Par récurrence forte :
• Pour n = 1, Time(1) ≤ c(log2 (1) + 1) = c
• Supposons que pour tout i ≤ n, Time(i) ≤ c(log2 (i) + 1) et montrons que Time(n + 1) ≤
c(log2 (n + 1) + 1):
On a Time(n + 1) ≤ c+Time( n+1
2 ) (cf. question 2). Comme
utiliser l’hypothèse de récurrence :
Time(n + 1)
n+1
2
≤ n (pour n > 0), on peut
≤ c + c(log2 ( n+1
2 ) + 1)
)
+
2)
= c(log2 ( n+1
2
= c(log2 (n + 1) − log2 (2) + 2)
= c(log2 (n + 1) − 1 + 2)
= c(log2 (n + 1) + 1)
Exercice 5: Algorithme itératif de recherche
Algorithme 1 : Un algorithme itératif de recherche par partition.
Cherche(T, n, v) : entier
Entrées : T un tableau trié, n sa dimension, v une valeur
Sorties : l’indice d’une cellule de tableau contenant v ou 0 s’il n’en existe pas
Données : bas, haut: entiers
bas ← 1
haut ← n
tant que bas ≤ haut faire
milieu ← (bas + haut)/2
si v = T [milieu] alors
retourner milieu
sinon si v < T [milieu] alors
haut ← milieu − 1
sinon
bas ← milieu + 1
finsi
fin tant que
retourner 0
1. Expliquer comment l’algorithme 1 procède pour obtenir un fonctionnement similaire au premier
programme de la question 3. En quoi est-il plus efficace?
2. Programmer en python l’algorithme 1.
3. Modifier le programme pour qu’il renvoie le plus petit indice comme dans la question 1.
4. Modifier le programme de la question précédente pour qu’il renvoie le nombre d’indices i tels que
T [i] = v.
1. La version itérative utilise deux variables bas et haut et une boucle tant que. Le coût en
espace mémoire est constant, pas de risque de saturation de la pile d’exécution.
2. def chercheTableauTriePPIIteratif (T, v):
temp = 0
bas = 1
haut = len (T) - 1
while bas <= haut:
milieu = (bas + haut) / 2
if v == T [milieu]:
temp = milieu
haut = milieu - 1
else:
if v < T [milieu]:
haut = milieu - 1
else:
bas = milieu + 1
return temp
T = [1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 9, 10]
print(chercheTableauTriePPIIteratif (T, 7))
print(chercheTableauTriePPIIteratif (T, 10))
print(chercheTableauTriePPIIteratif (T, 12))
en algorithmique :
CherchePPI_it(T, n, v) : entier
Entrées : T un tableau trié, n sa dimension, v une valeur
Sorties : valeur du plus petit indice contenant v ou 0 s’il n’en
existe pas
Données : temp, bas, haut : entiers
temp <- 0
bas <- 1
haut <- n
tant que bas <= haut faire
milieu <- (bas + haut)/2
si v = T [milieu] alors
temp <- milieu
haut <- milieu - 1
sinon
si v < T [milieu] alors
haut <- milieu - 1
sinon
bas <- milieu + 1
finsi
finsi
fin tant que
retourner temp
3. def nombreIndices (T, v):
count = 0
bool = True
bas = 1
haut = len (T) - 1
while bas <= haut and bool == True:
milieu = (bas + haut) / 2
if v == T [milieu]:
bool = False
count = count + 1
for i in range (bas, milieu):
if v == T [i]:
count = count + 1
for i in range (milieu + 1, haut + 1):
if v == T [i]:
count = count + 1
else:
if v < T [milieu]:
haut = milieu - 1
else:
bas = milieu + 1
return count
T = [1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 9, 10]
print(nombreIndices (T, 7))
print(nombreIndices (T, 10))
print(nombreIndices (T, 12))
en algorithmique :
NombreIndices(T, n, v) : entier
Entrées : T un tableau trié, bas et haut deux bornes, v une valeur
Sorties : le nombre d’indices i tels que T[i] = v.
Données : count : entiers
count <- 0
bool <- vrai
bas <- 1
haut <- n
tant que bas <= haut et bool = vrai faire
milieu <- (bas + haut)/2
si v = T [milieu] alors
bool <- faux
count <- count + 1
pour i = bas a milieu-1 faire
si v = T[i] alors
count <- count + 1
finsi
finpour
pour i = milieu+1 a haut faire
si v = T[i] alors
count <- count + 1
finsi
finpour
sinon
si v < T [milieu] alors
haut <- milieu - 1
sinon
bas <- milieu + 1
finsi
finsi
fin tant que
retourner count
Téléchargement