Adloun

Dichotomie, voisins et gloutons

Cours · NSI (première), chapitre 8 · première, spécialité numérique et sciences informatiques · le début du chapitre, la suite sur Adloun

La recherche dichotomique : dans un tableau trié, on élimine à chaque étape la moitié des cases restantes.

Le chapitre précédent a démontré la correction de boucles ; celui-ci en tire parti pour trois algorithmes qui, chacun, illustrent une idée différente. La recherche dichotomique montre ce qu'on gagne à exploiter une structure — ici, le fait que le tableau soit trié. Les plus proches voisins montrent qu'un algorithme peut prédire. Les algorithmes gloutons montrent qu'une stratégie simple peut être excellente… ou fausse, et qu'il faut savoir dire laquelle.

8.1 La recherche dichotomique

8.1.1 Diviser l'intervalle par deux

Chercher un mot dans un dictionnaire papier, personne ne le fait en partant de la première page. On ouvre au milieu, on regarde si le mot cherché est avant ou après, et on recommence sur la moitié retenue. Chaque coup d'œil élimine la moitié de ce qui reste.

Capacité attendue

« Montrer la terminaison de la recherche dichotomique à l'aide d'un variant de boucle. »


def dichotomie(t, v):
    """Indice d'une occurrence de v dans le tableau TRIÉ t, ou -1 si absente.

    Précondition  : t est trié par ordre croissant.
    Postcondition : si le résultat r vaut -1, v ne figure pas dans t ;
                    sinon t[r] == v.
    """
    gauche = 0
    droite = len(t) - 1
    while gauche <= droite:
        # invariant : si v figure dans t, alors son indice est dans
        #             l'intervalle [gauche, droite]
        milieu = (gauche + droite) // 2
        if t[milieu] == v:
            return milieu
        elif t[milieu] < v:
            gauche = milieu + 1
        else:
            droite = milieu - 1
    return -1
Figure : Chaque comparaison élimine la moitié des candidats. Treize cases, puis six, puis deux : trente comparaisons suffisent pour un milliard d'éléments.
ImportantLa précondition n'est pas négociable

Sur un tableau non trié, cette fonction ne renvoie pas une erreur : elle renvoie une réponse fausse. Elle peut annoncer pour une valeur présente. C'est le cas le plus dangereux — un programme qui se trompe sans le dire — et c'est pourquoi la précondition « est trié » doit être vérifiée par celui qui appelle, ou coûteusement par la fonction elle-même.

8.1.2 La terminaison, par un variant

Démonstration (Terminaison)

Prenons pour variant la quantité

c'est-à-dire le nombre d'indices encore candidats.

Elle est entière. gauche et droite sont des entiers.

Elle est positive tant qu'on boucle. La condition d'entrée est gauche <= droite, donc à chaque tour.

Elle décroît strictement. Le corps exécute soit gauche = milieu + 1, soit droite = milieu - 1, où vérifie . Dans le premier cas, gauche augmente d'au moins ; dans le second, droite diminue d'au moins . Dans les deux cas, diminue d'au moins .

Une suite d'entiers positifs strictement décroissante étant finie, la boucle s'arrête.

Démonstration (Correction)

Invariant : si figure dans , alors il figure dans la tranche t[gauche..droite].

Initialisation. Au départ, la tranche est le tableau entier : l'invariant est trivialement vrai.

Conservation. Supposons l'invariant vrai. Si , alors — le tableau étant trié — tous les éléments d'indice sont : aucun ne peut valoir , et l'on peut sans risque poser . Le cas symétrique se traite de même. L'invariant est conservé.

Terminaison. La boucle s'achève quand , c'est-à-dire quand la tranche est vide. L'invariant dit alors que si figurait dans , il serait dans une tranche vide : c'est impossible, donc n'y figure pas, et renvoyer est juste.

Hors programme

Le programme note que « la preuve de la correction peut être présentée par le professeur » : c'est la terminaison, par le variant, qui est exigible de l'élève. La démonstration ci-dessus est donnée pour ceux qui veulent voir jusqu'au bout ce que « prouver un programme » veut dire.

Exercices du chapitre

La suite du cours · Tous les exercices du chapitre