Un tas est un arbre binaire complet où chaque parent respecte la propriété de tas - toujours plus petit (min-heap) ou toujours plus grand (max-heap) que ses enfants. « Complet » signifie que chaque niveau est rempli sauf éventuellement le dernier, qui se remplit de gauche à droite.
1 Min-heap
/ \
3 5
/ \
7 4
Comme il est complet, on le stocke dans un tableau à plat - pas besoin de pointeurs. Pour l'index i : enfant gauche = 2i + 1, enfant droit = 2i + 2, parent = (i - 1) // 2.
| Propriété | Min-Heap | Max-Heap | |-----------|----------|----------| | Racine | Plus petit élément | Plus grand élément | | Parent ≤ Enfants ? | ✅ Oui | ❌ Non (≥) | | Extraction donne | Minimum | Maximum |
Le module heapq de Python est un min-heap par défaut. Pour un max-heap, on inverse les valeurs à l'insertion et à l'extraction.
Insertion - ajouter en fin, puis remonter (échanger avec le parent tant que plus petit) :
import heapq
h = [1, 3, 5, 7]
heapq.heappush(h, 2) # h becomes [1, 2, 5, 7, 3]
Extraction du minimum - échanger la racine avec le dernier élément, retirer le dernier, puis descendre (échanger avec le plus petit enfant) :
smallest = heapq.heappop(h) # returns 1
Les deux opérations s'exécutent en O(log n) car la hauteur de l'arbre est log n.
Sign in to join the discussion
heapq.heapify(arr) convertit une liste en tas sur place en O(n), et non O(n log n). L'algorithme procède de bas en haut, faisant descendre chaque nœud interne. C'est l'un des résultats de complexité les plus surprenants en informatique.
Une file de priorité (priority queue) permet d'accéder toujours à l'élément de plus haute priorité. Les tas sont l'implémentation de référence car l'insertion et l'extraction sont en O(log n). Utilisez-en une chaque fois que vous avez besoin du « meilleur élément vu jusqu'ici ».
« Trouvez les K plus grands éléments d'un tableau non trié. »
On maintient un min-heap de taille K. Pour chaque élément, on l'insère ; si le tas dépasse K, on retire le plus petit. Ce qui reste, ce sont les K plus grands.
import heapq
def top_k(nums, k):
return heapq.nlargest(k, nums)
Temps : O(n log k) - bien mieux qu'un tri complet quand k ≪ n.
Vous avez besoin des 5 meilleurs scores parmi 1 million d'entrées. Quel type et quelle taille de tas ?
Insérer la tête de chaque liste dans un min-heap. Extraire le plus petit, puis insérer l'élément suivant de cette même liste. Répéter jusqu'à épuisement. Temps : O(N log K) où N est le nombre total d'éléments.
Maintenir deux tas : un max-heap pour la moitié inférieure et un min-heap pour la moitié supérieure. Équilibrer leurs tailles pour qu'elles diffèrent d'au plus 1. La médiane est toujours à l'une ou aux deux racines.
Lower half (max-heap): [1, 2, 3] ← max = 3
Upper half (min-heap): [4, 5, 6] ← min = 4
Median = (3 + 4) / 2 = 3.5
Dans l'approche à deux tas pour la médiane, où va d'abord un nouvel élément ?
Les tas excellent en ordonnancement : salles de réunion (suivre l'heure de fin la plus proche), planification de tâches avec refroidissement, files de jobs CPU. L'idée clé : un tas suit efficacement « ce qui finit en premier ».
| Besoin | Meilleur choix | Pourquoi | |--------|----------------|----------| | Extractions répétées du min/max | Tas | O(log n) insertion + extraction | | Données statiques, un seul tri | Tableau trié | O(n log n) une fois, O(1) accès | | Requêtes d'intervalle + statistiques d'ordre | BST équilibré | O(log n) pour tout | | Top-K depuis un flux | Tas de taille K | O(n log k) au total |
Quelle opération est en O(1) dans un min-heap ?
| Opération | Temps | |-----------|-------| | Insertion | O(log n) | | Extraction min/max | O(log n) | | Consulter min/max | O(1) | | Heapify | O(n) | | Top-K sur n éléments | O(n log k) |