Menu
Coddy logo textTech

Tas (tas binaire)

Dernière mise à jour

Un tas binaire est un arbre binaire complet qui garde la plus petite valeur (min-heap) ou la plus grande (max-heap) à la racine. Cette visualisation est un min-heap : chaque parent est inférieur ou égal à ses enfants. Pour ajouter une valeur, on l'ajoute à la prochaine position libre, puis on la "fait remonter" en l'échangeant avec son parent tant qu'elle est plus petite, jusqu'à ce que la propriété de tas soit rétablie. Appuyez sur lecture ci-dessus pour voir chaque nouvelle valeur remonter jusqu'à sa place.

Comme un tas est un arbre complet, il est stocké de façon compacte dans un tableau : les enfants du nœud i sont en 2i+1 et 2i+2. L'insertion et la suppression du minimum sont en O(log n) (un chemin de la racine à une feuille), tandis que consulter le minimum est en O(1) - exactement ce dont une file de priorité a besoin.

Complexité en temps et en espace

OpérationComplexitéRemarques
Consulter min/maxO(1)C'est toujours la racine
Insérer (push)O(log n)Remonter le long d'un chemin
Supprimer min/maxO(log n)Descendre le long d'un chemin
Construire le tasO(n)Heapify en une seule fois
EspaceO(n)Basé sur un tableau, sans pointeurs

Étape par étape (push)

ÉtapeCe qui se passe
1Ajoutez la nouvelle valeur à la fin (la prochaine feuille libre).
2Comparez-la à son parent.
3Si elle est plus petite (min-heap), échangez-la vers le haut.
4Répétez jusqu'à ce qu'elle ne soit plus plus petite que son parent ou atteigne la racine.

Exemple résolu

Construction d'un min-heap en insérant [5, 3, 8, 1, 4] une valeur à la fois :

PushTableau après remontéeAction
5[5]La première valeur devient la racine.
3[3, 5]3 < parent 5, donc elle remonte jusqu'à la racine.
8[3, 5, 8]8 > parent 5, donc elle reste une feuille.
1[1, 3, 8, 5]1 < parent 5, échange ; puis 1 < parent 3, remonte jusqu'à la racine.
4[1, 3, 8, 5, 4]4 > parent 3, donc elle reste ; le minimum 1 demeure à la racine.

Quand utiliser un tas

Utilisez-le quandÉvitez-le quand
Vous avez régulièrement besoin du plus petit ou du plus grand élément d'un ensemble changeant.Vous devez rechercher des valeurs arbitraires, pas seulement l'extrême - utilisez un BST ou un ensemble de hachage.
Vous implémentez une file de priorité pour Dijkstra, A* ou un ordonnanceur.Vous devez garder les données entièrement triées en permanence.
Vous voulez une insertion et une suppression du minimum en O(log n) avec une disposition en tableau compacte.Vous avez besoin d'une recherche ou d'une suppression rapide d'un élément précis (non racine).
Vous devez fusionner un flux d'éléments et les extraire par priorité.L'ensemble de données est minuscule et un parcours linéaire est plus simple et assez rapide.

Code de Heap (Priority Queue)

Une implémentation propre et exécutable de Heap (Priority Queue) en Python, JavaScript, Java, C++, C. Choisissez un langage, copiez le code ou ouvrez-le préchargé dans le Playground Coddy.

Code de Heap (Priority Queue) en Python

Python
1class MinHeap:2    def __init__(self):3        self.data = []4
5    def push(self, value):6        # Append at the end, then bubble up to restore order7        self.data.append(value)8        i = len(self.data) - 19        while i > 0:10            parent = (i - 1) // 211            if self.data[parent] <= self.data[i]:12                break13            self.data[i], self.data[parent] = self.data[parent], self.data[i]14            i = parent15
16    def pop(self):17        # Move the last leaf to the root, then sift it down18        top = self.data[0]19        last = self.data.pop()20        if self.data:21            self.data[0] = last22            self._sift_down(0)23        return top24
25    def _sift_down(self, i):26        n = len(self.data)27        while True:28            smallest = i29            left, right = 2 * i + 1, 2 * i + 230            if left < n and self.data[left] < self.data[smallest]:31                smallest = left32            if right < n and self.data[right] < self.data[smallest]:33                smallest = right34            if smallest == i:35                return36            self.data[i], self.data[smallest] = self.data[smallest], self.data[i]37            i = smallest38
39
40heap = MinHeap()41for value in [5, 3, 8, 1, 9, 2]:42    heap.push(value)43
44print("Heap array:     ", heap.data)45print("Popped in order:", [heap.pop() for _ in range(6)])
Exécutez ce code dans le Playground Python

FAQ sur les tas

À quoi sert un tas ?
Les tas implémentent des files de priorité, qui alimentent l'algorithme du plus court chemin de Dijkstra, les ordonnanceurs de tâches et les simulations d'événements. Ils sont aussi le moteur du heapsort. Chaque fois que vous avez régulièrement besoin du plus petit ou du plus grand élément d'un ensemble changeant, un tas est l'outil approprié.
Quelle est la différence entre un tas et un arbre binaire de recherche ?
Les deux sont des arbres binaires, mais un BST maintient un ordre complet de gauche à droite (permettant une recherche ordonnée), tandis qu'un tas ne garantit que la relation parent-enfant (min ou max à la racine). Un tas donne un accès O(1) à la valeur extrême ; un BST donne une recherche en O(log n) pour n'importe quelle valeur.
Pourquoi un tas est-il stocké dans un tableau ?
Comme un tas est toujours un arbre binaire complet, ses nœuds se mappent parfaitement sur les indices d'un tableau : les enfants de l'indice i sont en 2i+1 et 2i+2, et le parent en (i-1)/2. Cela évite de stocker des pointeurs vers les enfants et offre d'excellentes performances de cache.
Un tas est-il la même chose qu'un tableau trié ?
Non. Un tas garantit seulement que chaque parent est plus petit (min-heap) ou plus grand (max-heap) que ses enfants, donc les frères et cousins ne sont dans aucun ordre particulier. Un tableau trié est entièrement ordonné mais coûte O(n) à l'insertion, tandis qu'un tas insère en O(log n) tout en donnant un accès instantané à la valeur extrême.
Quand devrais-je utiliser un tas plutôt que simplement trier un tableau ?
Optez pour un tas quand les données changent sans cesse et que vous n'avez besoin que du minimum ou du maximum courant - insérer et extraire coûtent O(log n) chacun, contre re-trier tout le tableau. Si vous avez un ensemble de données statique et voulez tous les éléments dans l'ordre, un seul tri en O(n log n) est plus simple et souvent plus rapide.
Construire un tas à partir de n éléments prend-il O(n log n) ?
Pas si vous le construisez d'un seul coup. Insérer n éléments un par un est en O(n log n), mais le heapify ascendant, qui descend du dernier parent jusqu'à la racine, s'exécute en O(n) au total, car la plupart des nœuds sont proches du bas et ne descendent que sur une courte distance.
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER