Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Tas et files de priorité

Après cette leçon: Je peux garder le plus petit élément à portée de main avec un tas.

Leçon de 60 min3 commandesLab de compilation et d’architecture : gcc, flex, bison et RISC-V dans une VM

Traiter d’abord le ticket le plus urgent

Un tas est une structure qui garde toujours le plus petit élément tout en haut, prêt à être pris. Il sert à construire une file de priorité, où l’on sert d’abord l’élément le plus urgent.

Le service informatique d’une université reçoit des tickets : une panne du réseau, une imprimante, un mot de passe oublié. Il doit traiter d’abord le plus urgent, pas le plus ancien.

À la fin de cette leçon

Remarque

Je peux garder le plus petit élément à portée de main avec un tas.

Mots-clés

MotCe que ça veut direExemple
Tasun arbre rempli niveau par niveau où chaque parent est plus petit que ses enfants
File de prioritéune file où l’on sort d’abord l’élément le plus urgent
Prioritéun nombre : plus il est petit, plus c’est urgent1
Parentle nœud juste au-dessus d’un autre
Remonteréchanger un élément avec son parent plus grand
Descendreéchanger un élément avec son plus petit enfant

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Chaque parent est plus petit que ses enfants

Un tas est un arbre binaire rempli niveau par niveau, de gauche à droite, sans trou. Sa règle : chaque parent est plus petit que ses deux enfants.

Le plus petit élément est donc toujours à la racine. Les deux enfants ne sont pas rangés entre eux : le plus petit peut être à gauche ou à droite.

Un tas se range dans une simple liste

Un tas n’a pas de trou, donc une liste suffit. La racine est à l’indice 0. Le parent de l’indice i est à l’indice (i - 1) // 2.

Les enfants de l’indice i sont aux indices 2 × i + 1 et 2 × i + 2. Un calcul d’indice remplace le lien. La commande suivante calcule le parent de l’indice 6, puis les enfants de l’indice 2 : elle affiche 2, 5 et 6.

Parent de 6 et enfants de 2

Commande
python3 -c "print((6 - 1) // 2, 2 * 2 + 1, 2 * 2 + 2)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Exemple travaillé : indices d’un tas

IndiceValeurParentEnfants
02AucunIndices 1 et 2
15Indice 0Indices 3 et 4
23Indice 0Indice 5 seulement
39Indice 1Aucun
46Indice 1Aucun
58Indice 2Aucun

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Ajouter : poser en bas, puis remonter

Pour ajouter une valeur, on la pose à la première place libre, tout en bas. Tant qu’elle est plus petite que son parent, on l’échange avec lui : elle remonte.

Elle s’arrête dès que son parent est plus petit, ou à la racine. Il y a au plus un échange par niveau.

Exemple travaillé : ajouter 1 au tas

ÉtapeActionListe
DépartLe tas de la leçon2, 5, 3, 9, 6, 8
1Poser 1 en bas, indice 62, 5, 3, 9, 6, 8, 1
21 est plus petit que son parent 3 : échange2, 5, 1, 9, 6, 8, 3
31 est plus petit que son parent 2 : échange1, 5, 2, 9, 6, 8, 3
41 est à la racine : fin1, 5, 2, 9, 6, 8, 3

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Retirer le plus petit : faire descendre le dernier

Le plus petit est à la racine. On le retire, puis on met à sa place le dernier élément de la liste. Il est sans doute trop grand.

Tant qu’il est plus grand que son plus petit enfant, on l’échange avec cet enfant : il descend.

Exemple travaillé : retirer le plus petit

ÉtapeActionListe
DépartLe tas obtenu plus haut1, 5, 2, 9, 6, 8, 3
1Retirer 1, mettre le dernier (3) à la racine3, 5, 2, 9, 6, 8
2Le plus petit enfant de 3 est 2 : échange2, 5, 3, 9, 6, 8
3Le seul enfant de 3 est 8, plus grand : fin2, 5, 3, 9, 6, 8

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Une file de priorité de tickets

Code: python
import heapq

# La file de priorité d’un service informatique : le plus petit nombre passe d’abord.
tickets = []
heapq.heappush(tickets, [3, "mot de passe"])
heapq.heappush(tickets, [1, "panne du réseau"])
heapq.heappush(tickets, [2, "imprimante"])

while len(tickets) > 0:
    ticket = heapq.heappop(tickets)
    print(ticket[0], ticket[1])
# Ajoutez un ticket de priorité 1 à la liste, puis relancez.

Un tas coûte une dizaine d’étapes

Chaque échange change de niveau, donc une opération coûte au plus la hauteur du tas. Pour 1 000 éléments, c’est environ 10 étapes. Pour un million, environ 20.

Une liste non triée ajoute vite, mais trouver le plus petit demande de tout regarder. Le tas équilibre les deux.

Liste non triée ou tas : le coût

ÉlémentsStructureAjouterRetirer le plus petit
1 000Liste non triée11 000
1 000Tas1010
1 000 000Liste non triée11 000 000
1 000 000Tas2020

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Le module heapq fait ce travail pour vous

Python propose le module heapq, qui range un tas dans une liste comme nous venons de le faire. La première commande ajoute 5, 3, 8 puis 1, retire le plus petit, et affiche ce qui reste.

La seconde range d’un coup la liste 5, 3, 8, 1 en tas et l’affiche.

Quatre ajouts, un retrait

Commande
python3 -c "import heapq; t = []; [heapq.heappush(t, x) for x in [5, 3, 8, 1]]; print(heapq.heappop(t), t)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Ranger une liste en tas

Commande
python3 -c "import heapq; t = [5, 3, 8, 1]; heapq.heapify(t); print(t)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Erreur fréquente

Attention

Beaucoup pensent qu’un tas est une liste triée. Ce n’est pas vrai. Seul le plus petit est à sa place, à la racine. [2, 5, 3, 9] est un tas, alors que 5 vient avant 3. Garder un tas coûte moins cher que garder une liste triée.

Pour aller plus loin

Poussez dans un tas tous les nombres d’une liste, puis retirez-les un à un : ils sortent triés. C’est le tri par tas.

Estimez le nombre d’étapes pour 1 000 nombres, puis comparez avec l’insertion de chaque nombre dans une liste triée.

À propos de ce labo et de sa source: Lab de compilation et d’architecture : gcc, flex, bison et RISC-V dans une VM

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.