4SI
Objectifs
À la fin de ce chapitre, l’élève doit être capable de :
- trier un tableau d’entiers ou de chaînes par ordre croissant ou décroissant, selon quatre méthodes ;
- dérouler à la main chacune de ces méthodes sur un petit tableau ;
- rechercher un élément dans un tableau, de façon séquentielle ou dichotomique ;
- choisir une méthode de recherche selon que le tableau est trié ou non ;
- comparer les méthodes de tri selon le travail qu’elles effectuent.
Plan du chapitre
- Introduction
- Vocabulaire et exemple du chapitre
- Le tri à bulles
- Le tri par sélection
- La recherche d’un élément
- Le tri par insertion
- Le tri shell
- Comparaison des quatre tris
- Les erreurs les plus fréquentes
- Retenons
Les parties 3, 4 et 5 sont des rappels de 3ᵉ année ; les parties 6 et 7 sont nouvelles en 4ᵉ année.
1. Introduction
Activité 1
Un lycée compte 1 000 candidats au baccalauréat de la session 2027. Leurs noms sont rangés dans un tableau. Un parent vient demander si le nom de sa fille figure dans la liste.
Questions
- La liste est dans l’ordre des inscriptions. Combien de noms faut-il examiner, au pire, pour répondre ?
- La liste est maintenant dans l’ordre alphabétique. On ouvre la liste en son milieu : que peut-on conclure en comparant le nom cherché au nom trouvé à cet endroit ?
- En répétant ce procédé, combien de noms faut-il examiner, au pire ?
Réponse
Dans une liste en désordre, rien n’indique où se trouve le nom : il faut examiner les noms un par un, soit 1 000 noms au pire, lorsque le nom est absent ou placé en dernier.
Dans une liste triée, une seule comparaison avec le nom du milieu élimine la moitié de la liste : si le nom cherché vient avant dans l’alphabet, il ne peut se trouver que dans la première moitié, sinon dans la seconde. En répétant ce procédé, la partie restante est divisée par deux à chaque étape : 1 000, 500, 250, 125, 62, 31, 15, 7, 3, 1. Il suffit d’examiner 10 noms au pire.
Trier un tableau a donc un intérêt immédiat : cela rend la recherche beaucoup plus rapide. Ce chapitre étudie les deux questions ensemble : comment trier un tableau, et comment y rechercher un élément.
2. Vocabulaire et exemple du chapitre
2.1 Trier un tableau
Définition. Trier un tableau, c’est réorganiser ses éléments de façon qu’ils soient rangés dans un ordre donné : croissant, du plus petit au plus grand, ou décroissant, du plus grand au plus petit.
Toutes les méthodes de ce chapitre trient le tableau sur place : elles ne créent pas de second tableau, elles déplacent les éléments à l’intérieur du tableau lui-même. Le tableau est donc passé par référence (par adresse) à la procédure de tri : @T.
Pour décrire le travail d’une méthode, on utilise quatre mots.
| Mot | Sens |
|---|---|
| Parcours | un passage complet sur le tableau, ou sur une partie du tableau ; on dit aussi une passe |
| Comparaison | un test entre deux éléments, par exemple T[i] > T[i + 1] |
| Permutation | l’échange du contenu de deux cases, à l’aide d’une variable auxiliaire |
| Décalage | la copie d’un élément dans la case voisine, pour libérer une place |
La permutation de deux cases s’écrit toujours en trois affectations :
Aux ← T[i]
T[i] ← T[j]
T[j] ← Aux
Remarque importante. L’ordre des trois affectations est imposé. Écrire
T[i] ← T[j]en premier effacerait définitivement l’ancienne valeur deT[i].
2.2 L’exemple du chapitre
Toutes les méthodes du chapitre sont déroulées sur le même tableau de 7 entiers, afin de pouvoir les comparer à la fin :
| T | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Après le tri par ordre croissant, il doit contenir :
| T | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Les modules du chapitre utilisent le type suivant :
TDNT
| Nouveau type |
|---|
Tab = Tableau de 20 Entiers |
Pour chaque méthode, on comptera le nombre de parcours, de comparaisons et de permutations ou de décalages nécessaires pour trier ce tableau.
2.3 Trier des chaînes de caractères
Les chaînes se comparent avec les mêmes opérateurs que les nombres : <, >, =. La comparaison se fait caractère par caractère, de gauche à droite, selon le code ASCII : "Amine" < "Chaima" est vrai, puisque Ord("A") = 65 est inférieur à Ord("C") = 67.
Toutes les méthodes de ce chapitre s’appliquent donc sans modification à un tableau de chaînes : seul le type du tableau change.
Remarque importante. Les majuscules ont des codes plus petits que les minuscules :
"amine" < "Yasmine"est faux, puisqueOrd("a") = 97est supérieur àOrd("Y") = 89. Pour trier des noms dans l’ordre alphabétique, ils doivent être écrits de la même façon, par exemple avec une majuscule initiale.
3. Le tri à bulles
3.1 Principe
On parcourt le tableau en comparant chaque élément à son voisin de droite ; s’ils sont dans le mauvais ordre, on les permute. À la fin d’un parcours, le plus grand élément rencontré est arrivé en dernière position, comme une bulle qui remonte à la surface. On recommence les parcours tant qu’un parcours a produit au moins une permutation.
Premier parcours sur l’exemple du chapitre
i | Comparaison | Permutation ? | Tableau après |
|---|---|---|---|
| 0 | T[0] = 6 > T[1] = 2 | oui | 2 6 8 5 1 9 3 |
| 1 | T[1] = 6 > T[2] = 8 | non | 2 6 8 5 1 9 3 |
| 2 | T[2] = 8 > T[3] = 5 | oui | 2 6 5 8 1 9 3 |
| 3 | T[3] = 8 > T[4] = 1 | oui | 2 6 5 1 8 9 3 |
| 4 | T[4] = 8 > T[5] = 9 | non | 2 6 5 1 8 9 3 |
| 5 | T[5] = 9 > T[6] = 3 | oui | 2 6 5 1 8 3 9 |
Après ce premier parcours, le plus grand élément, 9, occupe la dernière case.
3.2 Méthode 1 : répéter tant qu’il y a des permutations
Procédure Tri_Bulles (@T : Tab, n : Entier)
DEBUT
Répéter
Permut ← Faux
Pour i de 0 à n - 2 Faire
Si T[i] > T[i + 1] Alors
Aux ← T[i]
T[i] ← T[i + 1]
T[i + 1] ← Aux
Permut ← Vrai
FinSi
Fin Pour
Jusqu'à Non(Permut)
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i, Aux | Entier |
Permut | Booléen |
La variable Permut est un drapeau : elle passe à Vrai dès qu’une permutation a lieu. Un parcours qui la laisse à Faux prouve que le tableau est trié.
Trace sur l’exemple du chapitre : état du tableau à la fin de chaque parcours.
| Départ | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| Parcours 1 | 2 | 6 | 5 | 1 | 8 | 3 | 9 |
| Parcours 2 | 2 | 5 | 1 | 6 | 3 | 8 | 9 |
| Parcours 3 | 2 | 1 | 5 | 3 | 6 | 8 | 9 |
| Parcours 4 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| Parcours 5 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Le parcours 5 ne produit aucune permutation : Permut reste à Faux et le tri s’arrête. Bilan : 5 parcours, 30 comparaisons, 11 permutations.
En détail
Le parcours 5 ne modifie rien, mais il est nécessaire : c’est lui qui constate que le tableau est trié. Sur un tableau déjà trié, la méthode 1 ne fait qu’un seul parcours.
3.3 Méthode 2 : la forme de référence en 4ᵉ année
La méthode 1 compare à chaque parcours tout le tableau, y compris la fin, qui est déjà en place : après le parcours 1, la case 6 contient définitivement 9 ; après le parcours 2, les cases 5 et 6 contiennent définitivement 8 et 9. La méthode 2 réduit la zone parcourue d’une case à chaque fois, en décrémentant n après chaque parcours : n représente alors le nombre de cases qui restent à trier.
Procédure Tri_Bulles (@T : Tab, n : Entier)
DEBUT
Répéter
Permut ← Faux
Pour i de 0 à n - 2 Faire
Si T[i] > T[i + 1] Alors
Aux ← T[i]
T[i] ← T[i + 1]
T[i + 1] ← Aux
Permut ← Vrai
FinSi
Fin Pour
n ← n - 1
Jusqu'à Non(Permut) Ou (n = 1)
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i, Aux | Entier |
Permut | Booléen |
Trace sur l’exemple du chapitre. Les cases entre crochets sont celles que le parcours a placées définitivement : elles ne seront plus parcourues.
| Départ | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| Parcours 1 | 2 | 6 | 5 | 1 | 8 | 3 | 9 |
| Parcours 2 | 2 | 5 | 1 | 6 | 3 | 8 | 9 |
| Parcours 3 | 2 | 1 | 5 | 3 | 6 | 8 | 9 |
| Parcours 4 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| Parcours 5 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| Parcours | i varie de 0 à | Comparaisons | Permutations | n en fin de parcours | Permut |
|---|---|---|---|---|---|
| 1 | 5 | 6 | 4 | 6 | Vrai |
| 2 | 4 | 5 | 3 | 5 | Vrai |
| 3 | 3 | 4 | 2 | 4 | Vrai |
| 4 | 2 | 3 | 2 | 3 | Vrai |
| 5 | 1 | 2 | 0 | 2 | Faux |
Bilan : 5 parcours, 20 comparaisons, 11 permutations. Les permutations sont les mêmes que dans la méthode 1 ; seules les comparaisons inutiles ont disparu : 20 au lieu de 30.
Remarque importante. Le paramètre
nest passé par valeur : la procédure travaille sur une copie den. La décrémenter ne modifie pas la variablendu programme appelant, qui garde la taille du tableau ; seul le tableauT, passé par référence (par adresse), est modifié.
Remarque importante. La condition d’arrêt est une disjonction : on s’arrête si plus rien ne permute, ou s’il ne reste qu’une case à trier. Sans
Ou (n = 1), un tableau qui permute jusqu’au dernier parcours utile en ferait un de plus, vide, avec la bornen - 2 = -1.
En détail
On aurait pu recopier n dans une variable locale, par exemple NC ← n, et décrémenter NC. Le tri serait le même, avec les mêmes parcours et les mêmes comparaisons. Décrémenter n directement économise seulement une variable locale et une affectation : c’est un gain de mémoire minime, et aucun gain de temps.
En Python
def Tri_Bulles(T, n):
Permut = True
while Permut and n > 1:
Permut = False
for i in range(n - 1):
if T[i] > T[i + 1]:
Aux = T[i]
T[i] = T[i + 1]
T[i + 1] = Aux
Permut = True
n = n - 1
En détail
Python n’a pas de boucle Répéter … Jusqu'à. La boucle while continue tant que la condition d’arrêt est fausse : Non(Non(Permut) Ou (n = 1)), c’est-à-dire Permut and n > 1. L’initialisation Permut = True garantit le premier parcours.
4. Le tri par sélection
4.1 Principe
On sélectionne le plus petit élément du tableau et on le place dans la première case, par une permutation. Puis on sélectionne le plus petit des éléments restants et on le place dans la deuxième case, et ainsi de suite jusqu’à l’avant-dernière case. La dernière case contient alors forcément le plus grand élément.
4.2 Algorithme
Procédure Tri_Selection (@T : Tab, n : Entier)
DEBUT
Pour i de 0 à n - 2 Faire
posmin ← i
Pour j de i + 1 à n - 1 Faire
Si T[j] < T[posmin] Alors
posmin ← j
FinSi
Fin Pour
Si posmin ≠ i Alors
Aux ← T[i]
T[i] ← T[posmin]
T[posmin] ← Aux
FinSi
Fin Pour
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i, j, posmin, Aux | Entier |
La boucle intérieure est la recherche de la position du minimum, déjà rencontrée avec la fonction pos_min_tab, mais limitée à la partie du tableau qui commence en i.
4.3 Trace sur l’exemple du chapitre
i | posmin | Minimum | Permutation |
|---|---|---|---|
| 0 | 4 | 1 | T[0] ↔ T[4] |
| 1 | 1 | 2 | aucune, 2 est déjà en place |
| 2 | 6 | 3 | T[2] ↔ T[6] |
| 3 | 3 | 5 | aucune |
| 4 | 4 | 6 | aucune |
| 5 | 6 | 8 | T[5] ↔ T[6] |
Les cases entre crochets sont définitivement placées.
| Départ | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| i = 0 | 1 | 2 | 8 | 5 | 6 | 9 | 3 |
| i = 1 | 1 | 2 | 8 | 5 | 6 | 9 | 3 |
| i = 2 | 1 | 2 | 3 | 5 | 6 | 9 | 8 |
| i = 3 | 1 | 2 | 3 | 5 | 6 | 9 | 8 |
| i = 4 | 1 | 2 | 3 | 5 | 6 | 9 | 8 |
| i = 5 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Bilan : 6 parcours, 21 comparaisons, 3 permutations. Le tri par sélection fait toujours le même nombre de comparaisons, quel que soit l’ordre de départ, mais très peu de permutations : au plus une par parcours.
En détail
Le test Si posmin ≠ i évite de permuter une case avec elle-même. Sans lui, le tri resterait correct, mais on compterait ici 6 permutations au lieu de 3.
En Python
def Tri_Selection(T, n):
for i in range(n - 1):
posmin = i
for j in range(i + 1, n):
if T[j] < T[posmin]:
posmin = j
if posmin != i:
Aux = T[i]
T[i] = T[posmin]
T[posmin] = Aux
5. La recherche d’un élément
5.1 La recherche séquentielle
On examine les éléments un par un, du premier au dernier, jusqu’à trouver l’élément cherché ou atteindre la fin du tableau. Cette méthode s’applique à n’importe quel tableau, trié ou non.
Elle s’écrit de quatre façons, toutes correctes : deux avec la boucle Tant que, deux avec la boucle Répéter … Jusqu'à.
Méthode 1 : avec un drapeau
Fonction Recherche_sequentielle (T : Tab, n, x : Entier) : Booléen
DEBUT
Trouve ← Faux
i ← 0
Tant que (i < n) Et (Non(Trouve)) Faire
Si T[i] = x Alors
Trouve ← Vrai
Sinon
i ← i + 1
FinSi
Fin Tant que
Retourner Trouve
FIN
TDOL
| Objet | Type / Nature |
|---|---|
Trouve | Booléen |
i | Entier |
Méthode 2 : la condition dans la boucle
Fonction Recherche_sequentielle (T : Tab, n, x : Entier) : Booléen
DEBUT
i ← 0
Tant que (i < n) Et (T[i] ≠ x) Faire
i ← i + 1
Fin Tant que
Retourner i < n
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i | Entier |
Dans la méthode 2, la boucle s’arrête pour l’une des deux raisons de sa condition. Si elle s’arrête parce que T[i] = x, alors i < n ; si elle s’arrête parce que i = n, l’élément est absent. La fonction retourne donc le résultat de la comparaison i < n.
**Méthode 3 : Répéter avec un drapeau**
Fonction Recherche_sequentielle (T : Tab, n, x : Entier) : Booléen
DEBUT
Trouve ← Faux
i ← 0
Répéter
Si T[i] = x Alors
Trouve ← Vrai
Sinon
i ← i + 1
FinSi
Jusqu'à (Trouve) Ou (i = n)
Retourner Trouve
FIN
TDOL
| Objet | Type / Nature |
|---|---|
Trouve | Booléen |
i | Entier |
**Méthode 4 : Répéter avec la condition d’arrêt**
Fonction Recherche_sequentielle (T : Tab, n, x : Entier) : Booléen
DEBUT
i ← -1
Répéter
i ← i + 1
Jusqu'à (T[i] = x) Ou (i = n - 1)
Retourner T[i] = x
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i | Entier |
Dans la méthode 4, i vaut au plus n - 1 à la sortie de la boucle : on ne peut donc pas retourner i < n, qui serait toujours vrai. On retourne le résultat du test T[i] = x. Lorsque x est le dernier élément, les deux conditions d’arrêt sont vraies en même temps, et c’est encore ce test qui donne la bonne réponse : sur l’exemple du chapitre, la recherche de 3 et la recherche de 4 s’arrêtent toutes deux en i = 6, la première retourne Vrai, la seconde Faux.
Remarque importante. La boucle
Répéterexécute son corps au moins une fois : les méthodes 3 et 4 lisentT[0]avant tout test. Elles supposent donc que le tableau contient au moins un élément,n ≥ 1. Les méthodes 1 et 2, avecTant que, fonctionnent aussi sur un tableau vide : c’est pourquoi on les préfère.
Trace sur l’exemple du chapitre, T = 6 2 8 5 1 9 3.
Recherche de 5
i | T[i] | T[i] ≠ 5 |
|---|---|---|
| 0 | 6 | Vrai |
| 1 | 2 | Vrai |
| 2 | 8 | Vrai |
| 3 | 5 | Faux |
Recherche de 4
i | T[i] | T[i] ≠ 4 |
|---|---|---|
| 0 à 6 | 6, 2, 8, 5, 1, 9, 3 | Vrai à chaque tour |
| 7 | la boucle s’arrête : i < n est faux |
La recherche de 5 s’arrête en i = 3 et retourne Vrai, après 4 comparaisons. La recherche de 4 parcourt tout le tableau et retourne Faux, après 7 comparaisons. Une recherche sans succès examine toujours tous les éléments.
En Python
Python n’a pas de boucle Répéter … Jusqu'à : on traduit les méthodes écrites avec Tant que. Voici la méthode 2.
def Recherche_sequentielle(T, n, x):
i = 0
while (i < n) and (T[i] != x):
i = i + 1
return i < n
5.2 La recherche dichotomique
Lorsque le tableau est trié, on compare l’élément cherché à l’élément du milieu de la zone de recherche. Selon le résultat, on poursuit la recherche dans la moitié gauche ou dans la moitié droite, et l’on recommence. La zone de recherche, délimitée par les indices d et f, est divisée par deux à chaque tour.
Fonction Recherche_dichotomique (T : Tab, n, x : Entier) : Booléen
DEBUT
d ← 0
f ← n - 1
Trouve ← Faux
Tant que (d ≤ f) Et (Non(Trouve)) Faire
Milieu ← (d + f) Div 2
Si T[Milieu] = x Alors
Trouve ← Vrai
Sinon Si T[Milieu] > x Alors
f ← Milieu - 1
Sinon
d ← Milieu + 1
FinSi
Fin Tant que
Retourner Trouve
FIN
TDOL
| Objet | Type / Nature |
|---|---|
d, f, Milieu | Entier |
Trouve | Booléen |
La recherche dichotomique s’écrit aussi avec la boucle Répéter … Jusqu'à. La condition d’arrêt réunit les deux raisons de s’arrêter : l’élément est trouvé, ou la zone de recherche est vide.
Fonction Recherche_dichotomique (T : Tab, n, x : Entier) : Booléen
DEBUT
d ← 0
f ← n - 1
Trouve ← Faux
Répéter
Milieu ← (d + f) Div 2
Si T[Milieu] = x Alors
Trouve ← Vrai
Sinon Si T[Milieu] > x Alors
f ← Milieu - 1
Sinon
d ← Milieu + 1
FinSi
Jusqu'à (Trouve) Ou (d > f)
Retourner Trouve
FIN
Le TDOL est le même. Comme pour la recherche séquentielle, cette forme suppose n ≥ 1 : sur un tableau vide, le premier tour lirait T[0], qui n’existe pas.
Trace sur le tableau trié de l’exemple
| T | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| Recherche de 6 | d | f | Milieu | T[Milieu] | Décision |
|---|---|---|---|---|---|
| Tour 1 | 0 | 6 | 3 | 5 | 5 < 6 : d ← 4 |
| Tour 2 | 4 | 6 | 5 | 8 | 8 > 6 : f ← 4 |
| Tour 3 | 4 | 4 | 4 | 6 | trouvé |
| Recherche de 4 | d | f | Milieu | T[Milieu] | Décision |
|---|---|---|---|---|---|
| Tour 1 | 0 | 6 | 3 | 5 | 5 > 4 : f ← 2 |
| Tour 2 | 0 | 2 | 1 | 2 | 2 < 4 : d ← 2 |
| Tour 3 | 2 | 2 | 2 | 3 | 3 < 4 : d ← 3 |
| Fin | 3 | 2 | d > f : absent |
Sur ce tableau de 7 éléments, la dichotomie conclut toujours en 3 tours au plus, contre 7 pour la recherche séquentielle. L’écart grandit avec la taille : 10 tours au plus pour 1 000 éléments, 20 tours au plus pour un million.
En détail
Le nombre maximal de tours est le nombre de fois que l’on peut diviser n par 2 avant d’atteindre 1, plus un : 3 pour n = 7, 10 pour n = 1 000, 20 pour n = 1 000 000.
5.3 La condition indispensable : un tableau trié
Remarque importante. La recherche dichotomique ne s’applique qu’à un tableau trié. Sur un tableau non trié, elle ne signale aucune erreur : elle donne simplement une réponse fausse.
Exemple. On applique la recherche dichotomique au tableau non trié de l’exemple du chapitre, pour chercher 1.
| T | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| Recherche de 1 | d | f | Milieu | T[Milieu] | Décision |
|---|---|---|---|---|---|
| Tour 1 | 0 | 6 | 3 | 5 | 5 > 1 : f ← 2 |
| Tour 2 | 0 | 2 | 1 | 2 | 2 > 1 : f ← 0 |
| Tour 3 | 0 | 0 | 0 | 6 | 6 > 1 : f ← -1 |
| Fin | 0 | -1 | d > f : absent |
La fonction retourne Faux, alors que 1 se trouve en T[4]. Au premier tour, la comparaison 5 > 1 a éliminé toute la moitié droite, parce qu’elle supposait que les éléments situés après 5 sont plus grands que 5. Sur ce tableau, la dichotomie déclare absents 4 des 7 éléments présents : 6, 8, 1 et 3.
C’est la raison d’être du couple tri et recherche : on trie une fois, puis chaque recherche est rapide.
| Recherche séquentielle | Recherche dichotomique | |
|---|---|---|
| Tableau | quelconque | trié obligatoirement |
| Principe | examiner les éléments un par un | diviser la zone de recherche par deux |
Tours au pire, n = 7 | 7 | 3 |
Tours au pire, n = 1 000 | 1 000 | 10 |
En Python
def Recherche_dichotomique(T, n, x):
d = 0
f = n - 1
Trouve = False
while (d <= f) and (not Trouve):
Milieu = (d + f) // 2
if T[Milieu] == x:
Trouve = True
elif T[Milieu] > x:
f = Milieu - 1
else:
d = Milieu + 1
return Trouve
6. Le tri par insertion
6.1 Principe
C’est la méthode du joueur de cartes qui range sa main : il prend les cartes une par une et insère chacune à sa place parmi celles qu’il tient déjà, qui sont rangées.
Au début de l’étape i, la partie gauche du tableau, de T[0] à T[i - 1], est déjà triée. On retire T[i] dans une variable aux, on décale d’une case vers la droite tous les éléments de la partie triée qui sont plus grands que aux, puis on dépose aux dans la case libérée.
6.2 Algorithme
Procédure Tri_Insertion (@T : Tab, n : Entier)
DEBUT
Pour i de 1 à n - 1 Faire
aux ← T[i]
j ← i
Tant que (j > 0) Et (T[j - 1] > aux) Faire
T[j] ← T[j - 1]
j ← j - 1
Fin Tant que
T[j] ← aux
Fin Pour
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i, j, aux | Entier |
Remarque importante. Le tri par insertion ne permute pas : il décale. La valeur à insérer est mise de côté dans
auxavant les décalages, qui écrasent la caseT[i], puis elle est déposée une seule fois, dansT[j].
La boucle Pour commence à 1 : une partie triée d’un seul élément, T[0], est triée par définition. La boucle Tant que s’arrête dès que l’on rencontre un élément inférieur ou égal à aux, ou que l’on atteint le début du tableau.
6.3 Trace sur l’exemple du chapitre
i | aux | Décalages | aux déposé en |
|---|---|---|---|
| 1 | 2 | 1 | T[0] |
| 2 | 8 | 0 | T[2] |
| 3 | 5 | 2 | T[1] |
| 4 | 1 | 4 | T[0] |
| 5 | 9 | 0 | T[5] |
| 6 | 3 | 4 | T[2] |
La case entre crochets est celle où aux vient d’être déposé.
| Départ | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| i = 1 | 2 | 6 | 8 | 5 | 1 | 9 | 3 |
| i = 2 | 2 | 6 | 8 | 5 | 1 | 9 | 3 |
| i = 3 | 2 | 5 | 6 | 8 | 1 | 9 | 3 |
| i = 4 | 1 | 2 | 5 | 6 | 8 | 9 | 3 |
| i = 5 | 1 | 2 | 5 | 6 | 8 | 9 | 3 |
| i = 6 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
**Détail de l’étape i = 3** : aux ← 5, la partie triée est 2 6 8.
j | Test T[j - 1] > aux | Action |
|---|---|---|
| 3 | T[2] = 8 > 5 : Vrai | T[3] ← 8, j ← 2 |
| 2 | T[1] = 6 > 5 : Vrai | T[2] ← 6, j ← 1 |
| 1 | T[0] = 2 > 5 : Faux | fin de la boucle, T[1] ← 5 |
Bilan : 6 parcours, 15 comparaisons, 11 décalages.
En détail
Le nombre de décalages est égal au nombre de permutations du tri à bulles : 11 dans les deux cas. Ce n’est pas un hasard : chacune de ces opérations corrige une et une seule paire d’éléments mal ordonnés. Mais un décalage est une seule affectation, alors qu’une permutation en demande trois.
Lorsque le tableau est déjà presque trié, le tri par insertion ne fait presque aucun décalage : aux étapes i = 2 et i = 5, aux reste en place après une seule comparaison.
En Python
def Tri_Insertion(T, n):
for i in range(1, n):
aux = T[i]
j = i
while j > 0 and T[j - 1] > aux:
T[j] = T[j - 1]
j = j - 1
T[j] = aux
7. Le tri shell
7.1 Principe
Le tri par insertion ne déplace un élément que d’une case à la fois. À l’étape i = 4 de l’exemple, le 1 a dû traverser quatre cases, au prix de quatre décalages, pour aller de T[4] à T[0].
Le tri shell, du nom de son inventeur Donald Shell, corrige ce défaut. C’est un tri par insertion qui compare d’abord des éléments distants de p cases, appelé le pas, pour déplacer rapidement les éléments loin de leur position. Le pas est ensuite réduit, jusqu’à 1 : le dernier parcours utile est alors un tri par insertion ordinaire, mais sur un tableau presque trié.
7.2 Algorithme
Procédure Tri_Shell (@T : Tab, n : Entier)
DEBUT
p ← 1
Tant que p < n Faire
p ← 3 * p + 1
Fin Tant que
Tant que p ≥ 1 Faire
p ← p Div 3
Pour i de p à n - 1 Faire
aux ← T[i]
j ← i
Tant que (j ≥ p) Et (T[j - p] > aux) Faire
T[j] ← T[j - p]
j ← j - p
Fin Tant que
T[j] ← aux
Fin Pour
Fin Tant que
FIN
TDOL
| Objet | Type / Nature |
|---|---|
p, i, j, aux | Entier |
Comparé au tri par insertion, le corps de la boucle Pour est le même, où le pas 1 est remplacé par le pas p : j - 1 devient j - p, et j > 0 devient j ≥ p.
7.3 Le calcul du pas
Le pas ne dépend que de n. La première boucle parcourt la suite 1, 4, 13, 40, 121, …, où chaque terme vaut 3p + 1, et s’arrête sur le premier terme qui atteint ou dépasse n. La seconde boucle redescend cette suite par divisions entières par 3, avant chaque parcours.
**Pour n = 7**
| Première boucle | p | p < 7 ? |
|---|---|---|
| initialisation | 1 | Vrai |
p ← 3 * 1 + 1 | 4 | Vrai |
p ← 3 * 4 + 1 | 13 | Faux, fin |
La seconde boucle applique ensuite les pas 13 Div 3 = 4, puis 4 Div 3 = 1, puis 1 Div 3 = 0.
7.4 Trace sur l’exemple du chapitre
Parcours de pas 4. Les éléments comparés sont distants de 4 cases : T[0] et T[4], T[1] et T[5], T[2] et T[6].
i | aux | Comparaison | Action |
|---|---|---|---|
| 4 | 1 | T[0] = 6 > 1 : Vrai | T[4] ← 6, puis T[0] ← 1 |
| 5 | 9 | T[1] = 2 > 9 : Faux | 9 reste en T[5] |
| 6 | 3 | T[2] = 8 > 3 : Vrai | T[6] ← 8, puis T[2] ← 3 |
| Départ | 6 | 2 | 8 | 5 | 1 | 9 | 3 |
| Pas 4 | 1 | 2 | 3 | 5 | 6 | 9 | 8 |
| Pas 1 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| Pas 0 | 1 | 2 | 3 | 5 | 6 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Les cases entre crochets sont celles que le parcours a modifiées. Après le seul parcours de pas 4, le 1 a sauté directement de T[4] à T[0], et le 3 de T[6] à T[2] : il ne reste qu’une paire mal ordonnée, 9 et 8. Le parcours de pas 1 la corrige par un seul décalage.
Bilan : 3 parcours, 17 comparaisons, 3 décalages, contre 11 décalages pour le tri par insertion.
Le parcours de pas 0. Le dernier parcours s’exécute avec p = 0. La condition T[j - 0] > aux compare alors chaque élément à lui-même : elle est fausse d’emblée, et le tableau n’est pas modifié. Ce parcours coûte 7 comparaisons sur les 17 ; il est inutile, mais on le laisse s’exécuter pour garder l’algorithme simple.
7.5 Pourquoi le pas 3p + 1 ?
Le principe du tri shell fonctionne avec toute suite de pas qui se termine par 1. Mais toutes les suites ne se valent pas. La suite 3p + 1 est celle retenue dans ce cours, pour deux raisons :
- elle se calcule à partir de
nseul, par deux boucles très courtes ; - deux pas successifs,
pet3p + 1, ne sont jamais multiples l’un de l’autre, puisque(3p + 1) Mod p = 1dès quep > 1: un parcours ne se contente pas de refaire les comparaisons du précédent.
Une suite plus naturelle en apparence, qui divise le pas par 2 en partant de n Div 2, a un défaut : lorsque n est une puissance de 2, tous ses pas sont pairs sauf le dernier, et les éléments des cases paires ne sont jamais comparés à ceux des cases impaires avant le dernier parcours.
En détail
Donald Shell, qui a inventé ce tri en 1959, divisait le pas par 2. La suite 3p + 1 a été proposée plus tard par Donald Knuth.
En Python
def Tri_Shell(T, n):
p = 1
while p < n:
p = 3 * p + 1
while p >= 1:
p = p // 3
for i in range(p, n):
aux = T[i]
j = i
while j >= p and T[j - p] > aux:
T[j] = T[j - p]
j = j - p
T[j] = aux
8. Comparaison des quatre tris
8.1 Bilan sur l’exemple du chapitre
Tableau de départ : 6 2 8 5 1 9 3.
| Tri | Idée en une phrase | Parcours | Comparaisons | Permutations ou décalages |
|---|---|---|---|---|
| À bulles (méthode 2) | Comparer chaque élément à son voisin et les permuter s’ils sont mal ordonnés, jusqu’à ce qu’un parcours ne permute plus rien. | 5 | 20 | 11 permutations |
| Par sélection | Chercher le plus petit des éléments restants et le placer à la suite de ceux déjà placés. | 6 | 21 | 3 permutations |
| Par insertion | Prendre chaque élément et l’insérer à sa place dans la partie gauche, déjà triée. | 6 | 15 | 11 décalages |
| Shell | Trier par insertion des éléments distants d’un pas p, puis réduire le pas jusqu’à 1. | 3 | 17, dont 7 au pas 0 | 3 décalages |
8.2 Trier par ordre décroissant
Chacune des quatre méthodes trie par ordre décroissant en inversant la comparaison entre éléments, et rien d’autre :
| Tri | Ordre croissant | Ordre décroissant |
|---|---|---|
| À bulles | T[i] > T[i + 1] | T[i] < T[i + 1] |
| Par sélection | T[j] < T[posmin] | T[j] > T[posmax] |
| Par insertion | T[j - 1] > aux | T[j - 1] < aux |
| Shell | T[j - p] > aux | T[j - p] < aux |
Les comparaisons sur les indices, comme j > 0 ou i < n, ne changent pas.
Application résolue 1 — La liste d’appel
À la rentrée 2027, un professeur saisit les prénoms des élèves de son groupe dans l’ordre où ils se sont inscrits. Il veut obtenir la liste dans l’ordre alphabétique, retrouver rapidement un élève, et afficher les élèves dont le prénom commence par une lettre donnée.
Les prénoms sont rangés dans un tableau T de n chaînes de caractères, déclaré ainsi :
| Nouveau type |
|---|
TabCh = Tableau de 40 Chaînes de caractères |
Exemple : n = 8.
| T | Yasmine | Amine | Rania | Chaima | Omar | Rami | Ines | Firas |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Travail demandé
- Écrire l’algorithme de la procédure
Trier(T, n)qui trie le tableauTpar ordre alphabétique, selon la méthode du tri par insertion. - Écrire l’algorithme de la fonction
Position(T, n, p)qui retourne la position du prénompdans le tableauTtrié, ou-1si ce prénom n’y figure pas. La recherche est dichotomique. - Écrire l’algorithme de la procédure
Afficher_Initiale(T, n, c)qui affiche, à raison d’un prénom par ligne, les prénoms du tableauTtrié qui commencent par la lettrec. Le parcours s’arrête dès que les prénoms suivants ne peuvent plus commencer parc.
N.B. Le tableau T est déjà rempli. On suppose que les prénoms sont distincts et commencent tous par une majuscule suivie de minuscules : le candidat n’est pas appelé à les vérifier.
Voir le corrigé
1. Trier
C’est le tri par insertion du paragraphe 6.2, appliqué à un tableau de chaînes : seul le type de aux change.
Procédure Trier (@T : TabCh, n : Entier)
DEBUT
Pour i de 1 à n - 1 Faire
aux ← T[i]
j ← i
Tant que (j > 0) Et (T[j - 1] > aux) Faire
T[j] ← T[j - 1]
j ← j - 1
Fin Tant que
T[j] ← aux
Fin Pour
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i, j | Entier |
aux | Chaîne de caractères |
Sur l’exemple, le tri fait 17 décalages et donne :
| T | Amine | Chaima | Firas | Ines | Omar | Rami | Rania | Yasmine |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
En détail
"Rami" < "Rania" est vrai : les trois premiers caractères sont égaux, et la comparaison se décide sur le quatrième, "m" contre "n".
2. Position
La fonction retourne un entier : la position, ou la valeur -1, qui ne peut pas être une position. Cette valeur sert aussi de condition d’arrêt : la boucle continue tant que la position n’a pas été trouvée.
Fonction Position (T : TabCh, n : Entier, p : Chaîne de caractères) : Entier
DEBUT
d ← 0
f ← n - 1
pos ← -1
Tant que (d ≤ f) Et (pos = -1) Faire
Milieu ← (d + f) Div 2
Si T[Milieu] = p Alors
pos ← Milieu
Sinon Si T[Milieu] > p Alors
f ← Milieu - 1
Sinon
d ← Milieu + 1
FinSi
Fin Tant que
Retourner pos
FIN
TDOL
| Objet | Type / Nature |
|---|---|
d, f, Milieu, pos | Entier |
Exemple. Sur le tableau trié, Position(T, 8, "Omar") retourne 4.
| Tour | d | f | Milieu | T[Milieu] | Décision |
|---|---|---|---|---|---|
| 1 | 0 | 7 | 3 | Ines | Ines < Omar : d ← 4 |
| 2 | 4 | 7 | 5 | Rami | Rami > Omar : f ← 4 |
| 3 | 4 | 4 | 4 | Omar | trouvé : pos ← 4 |
Position(T, 8, "Salma") retourne -1, après 4 tours.
En détail
Comparée à la fonction Recherche_dichotomique du paragraphe 5.2, cette fonction remplace le drapeau Trouve par la variable pos, qui porte à la fois le succès de la recherche et la position trouvée.
3. Afficher_Initiale
Le tableau étant trié, les prénoms qui commencent par c sont consécutifs. Une première boucle saute les prénoms dont l’initiale précède c ; une seconde affiche les prénoms qui commencent par c, et s’arrête au premier qui ne commence plus par c.
Procédure Afficher_Initiale (T : TabCh, n : Entier, c : Caractère)
DEBUT
i ← 0
Tant que (i < n) Et (T[i][0] < c) Faire
i ← i + 1
Fin Tant que
Tant que (i < n) Et (T[i][0] = c) Faire
Écrire_nl(T[i])
i ← i + 1
Fin Tant que
FIN
TDOL
| Objet | Type / Nature |
|---|---|
i | Entier |
Exemple. Afficher_Initiale(T, 8, "R") affiche :
Rami
Rania
Le parcours s’arrête sur T[7] = "Yasmine", sans avoir à examiner d’autres prénoms.
En détail
Sur un tableau non trié, il faudrait parcourir tout le tableau, puisqu’un prénom en R pourrait se trouver n’importe où. C’est l’ordre du tableau qui autorise l’arrêt anticipé.
Application résolue 2 — Le concours de programmation
Le club d’informatique d’un lycée organise en 2027 un concours de programmation. Les scores des équipes, des entiers positifs, sont rangés dans un tableau S de n entiers. Le jury veut afficher le classement du meilleur au moins bon score, ajouter le score d’une équipe arrivée en retard sans refaire le tri, et vérifier si un score donné a été obtenu.
Exemple : n = 6.
| S | 120 | 85 | 150 | 85 | 200 | 60 |
| 0 | 1 | 2 | 3 | 4 | 5 |
Travail demandé
- Écrire l’algorithme de la procédure
Trier_Decroissant(S, n)qui trie le tableauSpar ordre décroissant, selon la méthode du tri shell. - Écrire l’algorithme de la procédure
Inserer(S, n, x)qui insère le scorexdans le tableauStrié par ordre décroissant, de façon qu’il reste trié, et met à journ. - Écrire l’algorithme de la fonction
Existe(S, n, x)qui vérifie, par une recherche dichotomique, si le scorexfigure dans le tableauStrié par ordre décroissant.
N.B. Le tableau S est déjà rempli ; il est déclaré de type Tab. On suppose que S contient moins de 20 scores avant l’insertion : le candidat n’est pas appelé à le vérifier.
Voir le corrigé
1. Trier_Decroissant
C’est le tri shell du paragraphe 7.2, dont la comparaison entre éléments est inversée.
Procédure Trier_Decroissant (@S : Tab, n : Entier)
DEBUT
p ← 1
Tant que p < n Faire
p ← 3 * p + 1
Fin Tant que
Tant que p ≥ 1 Faire
p ← p Div 3
Pour i de p à n - 1 Faire
aux ← S[i]
j ← i
Tant que (j ≥ p) Et (S[j - p] < aux) Faire
S[j] ← S[j - p]
j ← j - p
Fin Tant que
S[j] ← aux
Fin Pour
Fin Tant que
FIN
TDOL
| Objet | Type / Nature |
|---|---|
p, i, j, aux | Entier |
Trace. Pour n = 6, les pas sont 4, 1 et 0.
| Départ | 120 | 85 | 150 | 85 | 200 | 60 |
| Pas 4 | 200 | 85 | 150 | 85 | 120 | 60 |
| Pas 1 | 200 | 150 | 120 | 85 | 85 | 60 |
| Pas 0 | 200 | 150 | 120 | 85 | 85 | 60 |
| 0 | 1 | 2 | 3 | 4 | 5 |
2. Inserer
On part de la fin du tableau et l’on décale vers la droite les scores plus petits que x, puis on dépose x dans la case libérée. C’est exactement une étape du tri par insertion.
Procédure Inserer (@S : Tab, @n : Entier, x : Entier)
DEBUT
j ← n
Tant que (j > 0) Et (S[j - 1] < x) Faire
S[j] ← S[j - 1]
j ← j - 1
Fin Tant que
S[j] ← x
n ← n + 1
FIN
TDOL
| Objet | Type / Nature |
|---|---|
j | Entier |
Exemple. L’insertion de 130 dans le tableau trié :
| Avant | 200 | 150 | 120 | 85 | 85 | 60 | |
| Après | 200 | 150 | 130 | 120 | 85 | 85 | 60 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 |
En détail
Le paramètre n est passé par référence (par adresse), @n, puisque la procédure modifie le nombre de scores. On ne retrie pas le tableau : il est déjà trié, et une seule étape d’insertion suffit à y placer le nouveau score.
3. Existe
C’est la recherche dichotomique du paragraphe 5.2 sur un tableau décroissant : les grands scores sont à gauche. Si l’élément du milieu est plus petit que x, le score cherché ne peut se trouver qu’à gauche.
Fonction Existe (S : Tab, n, x : Entier) : Booléen
DEBUT
d ← 0
f ← n - 1
Trouve ← Faux
Tant que (d ≤ f) Et (Non(Trouve)) Faire
Milieu ← (d + f) Div 2
Si S[Milieu] = x Alors
Trouve ← Vrai
Sinon Si S[Milieu] < x Alors
f ← Milieu - 1
Sinon
d ← Milieu + 1
FinSi
Fin Tant que
Retourner Trouve
FIN
TDOL
| Objet | Type / Nature |
|---|---|
d, f, Milieu | Entier |
Trouve | Booléen |
Exemple. Sur le tableau trié 200 150 120 85 85 60, Existe(S, 6, 85) retourne Vrai et Existe(S, 6, 100) retourne Faux.
9. Les erreurs les plus fréquentes
Les erreurs suivantes sont relevées sur les algorithmes du cours. Chaque résultat a été obtenu en exécutant l’algorithme erroné sur l’exemple du chapitre, 6 2 8 5 1 9 3.
| Instruction erronée | Instruction correcte | Conséquence |
|---|---|---|
Bulles : Pour i de 0 à n - 1 Faire | Pour i de 0 à n - 2 Faire | au dernier tour, T[i + 1] désigne une case hors du tableau |
Bulles : Jusqu'à Permut | Jusqu'à Non(Permut) Ou (n = 1) | le tri s’arrête après le parcours 1 : 2 6 5 1 8 3 9 |
Bulles : Jusqu'à Non(Permut) Et (n = 1) | Jusqu'à Non(Permut) Ou (n = 1) | le résultat est juste, mais un tableau déjà trié coûte 6 parcours au lieu d’un |
Sélection : posmin ← 0 | posmin ← i | le minimum est recherché dans tout le tableau : 8 1 2 3 5 6 9 |
Insertion : T[i] ← aux après la boucle | T[j] ← aux | aux est reposé à son ancienne place : 6 6 2 8 1 9 3 |
Insertion : Tant que (j ≥ 0) Et … | Tant que (j > 0) Et … | pour j = 0, T[j - 1] désigne une case hors du tableau |
Dichotomie : Tant que (d < f) Et … | Tant que (d ≤ f) Et … | la zone d’une seule case n’est jamais examinée : 1, 3, 6 et 9 sont déclarés absents du tableau trié |
Dichotomie : Milieu ← (d + f) / 2 | Milieu ← (d + f) Div 2 | / donne un réel, qui ne peut pas servir d’indice |
10. Retenons
Trier. Trier un tableau, c’est ranger ses éléments dans l’ordre croissant ou décroissant. Les tris du chapitre travaillent sur place : le tableau est passé par référence (par adresse),
@T.
Quatre méthodes. Bulles : permuter les voisins mal ordonnés. Sélection : placer le minimum des éléments restants. Insertion : insérer chaque élément dans la partie triée. Shell : insertion avec un pas décroissant 3p + 1, jusqu’à 1.
Bulles en 4ᵉ année. La forme de référence réduit la zone parcourue par
n ← n - 1,nétant passé par valeur, et s’arrête parJusqu'à Non(Permut) Ou (n = 1).
Rechercher. La recherche séquentielle s’applique à tout tableau. La recherche dichotomique exige un tableau trié ; elle divise la zone de recherche par deux à chaque tour.
Décroissant. On inverse la comparaison entre éléments, jamais les comparaisons sur les indices.
| Méthode | Tableau | Opération de base |
|---|---|---|
| Tri à bulles | quelconque | permutation de voisins |
| Tri par sélection | quelconque | permutation avec le minimum |
| Tri par insertion | quelconque | décalage d’une case |
| Tri shell | quelconque | décalage de p cases |
| Recherche séquentielle | quelconque | comparaison un par un |
| Recherche dichotomique | trié | comparaison au milieu |
Teste tes connaissances
Un quiz corrigé question par question, puis des flashcards pour mémoriser les notions du chapitre.

