IFT2121 H06 Devoir 6 Grenon, Nicola
Remise: 2006-03-17 GREN30077303
1. Donnez un algorithme qui fait moins que 3n/2 comparaisons pour trouver la plus grande et la plus
petite clé dans un fichier de n clés. Prouvez votre réponse.
minETmax(F[1..n]): M[min,max] {M[1] contiendra le min et M[2] contiendra le max}
Si taille(F) = 1
M[1] M[2] F[1]
Si taille(F) = 2
Si F[1] < F[2]
M[1] F[1]
M[2] F[2]
Sinon
M[1] F[2]
M[2] F[1]
Sinon
G minETmax(F[1..n/2]) {division entière}
D minETmax(F[(n/2)+1..n]) {division entière}
Si G[1]<D[1]
M[1] G[1]
Sinon
M[1] D[1]
Si G[2]>D[2]
M[2] G[2]
Sinon
M[2] D[2]
Retourner M
On reçoit la liste de clés dont il faut extraire le plus petit et le plus grand élément. Pour les déterminer, on divise en deux la
liste (un de plus à droite qu'à gauche si la longueur est impaire) et on s'appelle récursivement jusqu'à obtenir des listes de longueur
1 ou 2. Si la liste est de longueur 1, alors on retourne la me valeur pour min et max, si elle est de longueur deux on compare les
deux clés pour retourner correctement qui est min et qui est max. Au pire des cas on aura donc au bas de la pyramide n/2
comparaisons à effectuer si n est pair.
Au retour de l'appel récursif, la fonction a exactement 2 comparaisons à effectuer. Une entre les min et une entre les max. Il y
a n/4 fois ce travail à effectuer dans le pire des cas. On a donc 2n/4 = n/2 comparaisons à effectuer. À chaque retour successif on
traitera le résultat de deux fois plus d'éléments, donc on aura deux fois moins de tests à effectuer. On aura donc n/2k comparaisons
à effectuer une fois remonté à l'étage k (En prenant les feuilles de l'arbre binaire comme étage 0).
On a donc n/2 + (n/2k), k=1..plafond(lgn) comme nombre total de comparaisons.
(n/2k) étant une série bien connue dont la valeur tend vers 1 sans jamais la dépasser (1/2 + 1/4 + 1/8 + ... 1), on peut donc
conclure que le nombre total de comparaison ne dépassera jamais ½ + 1 = 3n/2.
Note: Il y a d'autres comparaison dans la structure de l'algorithme (test de longueur de la liste), pour la clarté de lecture je les ai ignorées, mais pour respecter
à la lettre les instructions, on pourrait les remplacer par un test d'existence sur l'élément 3 ou 2...
2. Donnez un algorithme pour trouver les deux éléments les plus grands dans un fichier de n clés en
utilisant moins que n + lgn comparaisons. Prouvez votre réponse.
maxEtsec(F[1..n]): M[max,sec] {M[1] contiendra le max et M[2] contiendra le second}
R maxPile(F[1..n]) {R[1] contiendra le max et R[2] une liste de
candidats au titre de «second»}
L R[2] {La liste de candidats}
S L[1] {Le premier candidat comme «second»}
Pour i=2 à taille(L)
Si L[i] > S
S L[i]
Retourner {R[1],S} {On retourne le maximum et le second}
maxListe(F[1..n]): R[max,liste] {On retourne le maximum et une liste de candidats}
Si taille(F) = 1
max F[1]
liste {}
Retourner {max,liste}
Si taille(F) = 2
Si F[1] > F[2]
max F[1]
liste F[2]
Sinon
max F[2]
liste F[1]
Retourner {max,liste}
Sinon
G maxListe(1..n/2) {On regarde dans la moitié gauche(division entière)}
maxg G[1]
listeg G[2]
D maxListe(n/2+1..n) {Moitié droite}
maxd D[1]
listed D[2]
Si maxg > maxd
liste pileg + maxd
Retourner {maxg, liste}
Sinon
liste piled + maxd
Retourner {maxd, liste}
L'algorithme fonctionne à la base simplement en divisant la liste dont il faut extraire le maximum en deux et en s'appelant
récursivement jusqu'à obtenir une liste de taille 1 ou 2. De laquelle on peut déterminer le maximum au moyen d'une simple
comparaison (ou aucune s'il n'y a qu'un élément). Les retour d'appel seront traités par paire en comparant les deux maximum et en
ne conservant que le plus grand.
Comme il y a n éléments, au plus bas niveau de la pyramide, on comparera, dans le pire des cas, les n éléments deux par
deux, ce qui nous donne n/2 comparaisons. Au retour d'appel, on aura un comparaison à faire par paire de maximum reçu, soit n/4
comparaisons dans le pire des cas. Et ainsi de suite on retrouvera finalement la série n/2 + n/4 + n/8 ... qui tend vers n. On
trouvera donc le maximum en n comparaisons.
Pour déterminer le second plus grand élément, on utilisera la structure existante déjà établie pour trouver le maximum pour
récolter la liste de tous les éléments correspondant à des candidats valables à ce titre. Par la suite, on effectuera une recherche
séquentielle simple parmi la liste des candidats recueillis pour déterminer le maximum. On aura ainsi notre second.
Pour déterminer les candidats à conserver pour la liste, il faut observer que dans l'arbre binaire formé par notre structure
récursive d'appels pour trouver le maximum, le second plus grand élément de notre liste ne peut être qu'un des éléments «battu»
sur son trajet par le maximum. Un des sous maximum éliminé par le vrai maximum donc. Ça se prouve facilement en gardant à
l'esprit que le second plus grand élément aurait été celui qui aurait été trouvé si notre vrai maximum n'avait pas été présent. Il a
donc obligatoirement été bloqué dans sa progression par notre vrai maximum.
Donc on accumule à chaque comparaison chaque étage de la pyramide que l'on remonte) la liste des éléments ayant été
exclus par notre maximum actuel et seulement ceux-là. Comme dans l'arbre binaire formé la hauteur est bornée par lgn, il ne peut
y avoir qu'au maximum lgn candidats dans la liste finale. La recherche séquentielle devra donc faire lgn -1comparaisons.
On a donc une recherche du maximum en n comparaisons dans le pire des cas et une recherche de second en lgn-1
comparaisons dans le pire des cas, d'où moins de n + lgn comparaisons au total.
Note: Il y a d'autres comparaison dans la structure de l'algorithme (test de longueur de la liste), pour la clarté de lecture je les ai ignorées, mais pour respecter
à la lettre les instructions, on pourrait les remplacer par un test d'existence sur l'élément 3 ou 2...
1 / 2 100%