Problèmatique
Supposons que nous avons déclaré un tableau tab
d'entiers comme suit :
Variables
tab : tableau MIN à MAX de entiers
Supposons que ce tableau est rempli d'entiers inconnus mais triés dans l'ordre croissant.
Proposez un algorithme qui, étant donné un entier indiqué par l'utilisateur, trouve son indice dans le tableau. On supposera que l'entier indiqué par l'utilisateur est effectivement dans le tableau.
Aide
Vous remarquerez que ce problème s'apparente au problème de recherche d'un mot dans le dictionnaire. Pensez donc à la méthode que vous employez dans cette situation...
Solutions
Solutions moyennes
Voici une solution, qui n'est pas celle attendue. L'algorithme parcourt le tableau du début à la fin et compare l'élément à l'entier indiqué par l'utilisateur. Il s'arrête lorsqu'il est trouvé. Remarquez que la faiblesse de cette algorithme provient du fait qu'il fonctionne même quand le tableau n'est pas trié, il n'exploite donc pas cet avantage trop important pour être négligé.
1Algorithme recherche
2Variables
3 q : entier (* l'entier recherché *)
4 i : entier (* ce sera l'indice de parcours *)
5Début
6 Afficher("Donner l'entier à trouver")
7 Lire(q)
8 i ← MIN
9 tantque tab[i] != q
10 i ← i+1
11 ftq
12 Afficher("L'indice où se trouve ", q ," est ", i)
13Fin
L'algorithme suivant fonctionne mais à le défaut de continuer à parcourir le tableau même quand l'élément a été trouvé.
1Algorithme recherche_mauvais
2Variables
3 q : entier (* l'entier recherché *)
4 i : entier (* ce sera l'indice de parcours pour la boucle *)
5 resultat : entier (* l'indice résultat sera stocké ici *)
6Début
7 Afficher("Donner l'entier à trouver")
8 Lire(q)
9 i ← MIN
10 pour i de MIN à MAX (* on parcourt tout le tableau *)
11 si tab[i] = q alors resultat ← i (* si on a trouvé on mémorise l'indice *)
12 ftq
13 Afficher("L'indice où se trouve ", q ," est ", résultat)
14Fin
Solution attendue
Voici enfin la solution attendue. Vous étiez peut-être arrivé à cette déduction seul ou en consultant l'aide mais vous avez compris que ce problème s'apparente à celui de la recherche dans un dictionnaire. En effet, on cherche un mot dans un ensemble de mots inconnus mais triés.
Si vous avez déjà cherché un mot dans le dictionnaire, vous avez certainement remarqué que lire le premier, regarder si c'est celui qu'on cherche, puis passer au suivant, et ainsi de suite n'est pas la solution la plus efficace...
La solution est donc l'algorithme de recherche dichotomique (du grec « dichotomie » : « couper en deux »). On ouvre le dictionnaire au milieu et un prend un mot au hasard, si le mot qu'on cherche est avant, recommence avec la première moitié du dictionnaire, s'il est après, avec la deuxième moitié. Dans la bonne moitié on prend un mot au milieu, etc...
1Algorithme recherche_dichotomique
2Variables
3 q : entier (* l'entier recherché *)
4 i : entier (* ce sera l'indice de parcours pour la boucle *)
5 deb, fin : entiers (* deux entiers pour désigner le début et la fin de la zone dans laquelle on recherche *)
6Début
7 Afficher("Donner l'entier à trouver")
8 Lire(q)
9 (* on commence en recherchant dans tout le tableau *)
10 deb ← MIN
11 fin ← MAX
12 répéter
13 i = arrondir((fin+deb)/2) (* on prend i entre deb et fin *)
14 si tab[i] > q
15 alors fin ← i (* on est tombé trop haut : on ramène la borne supérieure *)
16 sinon si tab[i] < q
17 alors deb ← i (* on est tombé trop bas : on ramène la borne inférieure *)
18 jusqu'à tab[i]=q
19 Afficher("L'indice où se trouve ", q ," est ", i)
20Fin
Traduction en Pascal
Voilà sa traduction en Pascal, le tableau étant rempli à la main :
1program recherche_dichotomique;
2Const
3 MIN = 0;
4 MAX = 10;
5Var
6 tab : array [MIN..MAX] of integer;
7 q : integer; (* l'entier recherché *)
8 i : integer; (* ce sera l'indice de parcours pour la boucle *)
9 deb, fin : integer; (* deux entiers pour désigner le début et la fin de la zone dans laquelle on recherche *)
10Begin
11 tab[0] := 1;
12 tab[1] := 4;
13 tab[2] := 9;
14 tab[3] := 10;
15 tab[4] := 24;
16 tab[5] := 24;
17 tab[6] := 74;
18 tab[7] := 75;
19 tab[8] := 76;
20 tab[9] := 90;
21 tab[10] := 99;
22 Writeln('Donner l''entier à trouver : ');
23 Readln(q);
24 (* on commence en recherchant dans tout le tableau *)
25 deb := MIN;
26 fin := MAX;
27 repeat
28 i := round((fin+deb)/2); (* on prend i entre deb et fin *)
29 if tab[i] > q
30 then fin := i (* on est tombé trop haut : on ramène la borne supérieure *)
31 else if tab[i] < q
32 then deb := i; (* on est tombé trop bas : on ramène la borne inférieure *)
33 until tab[i]=q;
34 Writeln('L''indice où se trouve ', q ,' est ', i);
35End.