Dichotomie
9 mars 2007
static int dicho(int[] t, int i)
int bas=0, haut=t.length-1;
while (bas <= haut) {
int centre = (haut+bas)/2;
if (i==t[centre])
return centre; //(1)
if (i < t[centre])
haut=centre-1;
else
bas=centre+1;
}
return -1;
}
De façon générale, il faut être très attentif sur ce qui se passe lorsque l’intervalle devient très
petit.
Terminaison : si on note l=haut bas,ldécroit au moins de 1 à chaque passage dans la boucle
i! = t[centre](en général il est même plus que divisé par 2, mais attention à ce qui peut se
passer pour les petites valeurs. . .).
Nécessairement, si on n’a jamais i== t[centre],lva donc finir par vérifier l < 0, ce qui est la
condition d’arrêt.
Invariant de boucle : «si iest dans le tableau, il est à un indice compris entre bas et haut». En
effet, cette propriété est vraie avant la boucle. Si elle est vraie au début de la boucle (iest dans
[bas, haut]), et si on a par exemple i < t[centre](strictement !), nécessairement, si iest dans
le tableau, il est dans [bas, centre 1] par monotonie du tableau (le seul cas problématique est
celui où t[centre 1] < i < t[centre]. Dans ce cas, in’apparait pas dans le tableau, et notre
propriété reste vraie).
On peut donc maintenant prouver simplement l’algorithme : on voit déjà que s’il retourne, il
retourne une valeur correcte. Reste à voir qu’il ne rate pas i. Si iest dans le tableau, on a à
tout moment que iapparaît entre bas et haut. On commence par regarder ce qu’il se passe
lorsque l== 0 ou l== 1. Une petite étude de cas permet de voir que l’on trouve bien idans
ces cas là. Dans le cas général, on remarque juste que si l’algorithme de retourne pas, il passe
1
forcément par les cas l== 0 ou l== 1 (là aussi, une petite étude de cas est nécessaire :
regarder ce qui se passe pour l== 2,l== 3,l== 4 et l > 4), ce qui permet de conclure.
On a ainsi : «la boucle retourne via (1) si et seulement si iest dans le tableau, et la valeur
retournée est correcte». On en déduit «l’algorithme retourne -1 si et seulement si in’est pas
dans le tableau», et le comportement de l’algorithme est entièrement prouvé.
Complexité : notons nla longueur du tableau passé en argument.On a vu que l’on passait né-
cessairement à l== 0 ou l== 1. Une fois que l’on est à l== 0 ou l== 1, l’algorithme
termine en un temps constant (< t0, indépendant de n). la question est de savoir au bout de
combien de temps on arrive à 0ou 1. Au début, on a l0=n, puis trivialement li+1 li/2
pour li! = 0 ou 1. Notons k=ceil(log(n)) ceil désigne la partie entière +1. On a alors
2kn, soit n/2k1. Donc au plus au bout kitérations, on aura l1(et l’algorithme finit
alors en temps constant). La complexité est donc inférieure à O(log(n)). Resterait à montrer
qu’il y a des cas où cette borne est atteinte pour voir que la complexité au pire est exactement
O(log(n)) (ce qui est le cas).
2
1 / 2 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !