< Algorithmique impérative

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.
Cet article est issu de Wikibooks. Le texte est sous licence Creative Commons - Attribution - Partage dans les Mêmes. Des conditions supplémentaires peuvent s'appliquer aux fichiers multimédias.