Menu
Coddy logo textTech

Heap Sort

Dernière mise à jour

Le tri par tas traite le tableau comme un tas binaire. Il construit d'abord un max-heap, de sorte que le plus grand élément se trouve à la racine (indice 0). Ensuite il échange à plusieurs reprises la racine avec le dernier élément non trié - fixant le maximum à sa place - et fait descendre la nouvelle racine pour restaurer la propriété de tas. Appuyez sur lecture ci-dessus pour voir la construction du tas et les extractions.

Le tri par tas garantit un temps en O(n log n) comme le tri fusion, mais trie sur place avec seulement O(1) d'espace supplémentaire. Il n'est pas stable et tend à avoir un moins bon comportement de cache que le tri rapide, il est donc souvent choisi lorsqu'une borne garantie et une mémoire constante importent toutes deux.

Complexité en temps et en espace

CasComplexitéNotes
Meilleur casO(n log n)Construction + n extractions
Cas moyenO(n log n)Ordre aléatoire
Pire casO(n log n)Garanti
EspaceO(1)Sur place
StableNonLa descente réordonne les éléments égaux

Étape par étape

ÉtapeCe qui se passe
1Construire un max-heap à partir du tableau (descendre depuis le dernier parent).
2Échanger la racine (maximum) avec le dernier élément du tas.
3Réduire le tas d'un - ce dernier emplacement est maintenant trié.
4Faire descendre la nouvelle racine pour restaurer la propriété de max-heap.
5Répéter jusqu'à ce que le tas n'ait plus qu'un élément.

Exemple détaillé

Tri de [3, 1, 6, 5, 2, 4]. La barre | marque la limite entre le tas qui rétrécit et la queue triée :

PasseTableauAction
Construire le tas[6, 5, 4, 1, 2, 3]Descendre depuis le dernier parent pour construire le max-heap ; 6 est maintenant à la racine.
1[5, 3, 4, 1, 2 | 6]Échanger la racine 6 avec le dernier emplacement, réduire le tas et faire descendre 3.
2[4, 3, 2, 1 | 5, 6]Sortir la racine 5, puis faire descendre 2 pour que 4 remonte à la racine.
3[3, 1, 2 | 4, 5, 6]Sortir la racine 4, puis faire descendre 1 pour que 3 remonte à la racine.
4[2, 1 | 3, 4, 5, 6]Sortir la racine 3 ; 2 satisfait déjà la propriété de tas.
5[1 | 2, 3, 4, 5, 6]Sortir la racine 2 ; il reste un élément, donc le tableau est trié.

Quand utiliser le tri par tas

Utilisez-le quandÉvitez-le quand
Vous avez besoin d'un pire cas garanti en O(n log n) sans risque de O(n²).Vous avez besoin d'un tri stable qui préserve l'ordre des clés égales.
La mémoire est limitée - il trie sur place avec seulement O(1) d'espace supplémentaire.La performance de cache compte et les données tiennent en mémoire - le tri rapide est généralement plus rapide.
Vous maintenez déjà un tas (par ex. une file de priorité) sur les données.Vous voulez le moins de comparaisons - le tri fusion et le tri rapide en font souvent moins en pratique.
Une entrée non fiable pourrait déclencher le pire cas du tri rapide et vous ne pouvez pas randomiser.Les données sont presque triées - le tri par insertion s'exécute en temps quasi linéaire sur elles.

Code de Heap Sort

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

Code de Heap Sort en Python

Python
1def heap_sort(a):2    n = len(a)3    # Build a max-heap, deepest parent first4    for i in range(n // 2 - 1, -1, -1):5        sift_down(a, i, n)6    # Repeatedly move the max to the end and shrink the heap7    for end in range(n - 1, 0, -1):8        a[0], a[end] = a[end], a[0]9        sift_down(a, 0, end)10    return a11
12
13def sift_down(a, i, size):14    while True:15        largest = i16        left, right = 2 * i + 1, 2 * i + 217        if left < size and a[left] > a[largest]:18            largest = left19        if right < size and a[right] > a[largest]:20            largest = right21        if largest == i:22            return23        a[i], a[largest] = a[largest], a[i]24        i = largest25
26
27nums = [12, 11, 13, 5, 6, 7]28print("Before:", nums)29heap_sort(nums)30print("After: ", nums)
Exécutez ce code dans le Playground Python

FAQ sur le tri par tas

Quelle est la complexité temporelle du tri par tas ?
Le tri par tas est en O(n log n) dans le meilleur, le moyen et le pire cas. Construire le tas est en O(n) et chacune des n extractions coûte O(log n). Il utilise O(1) d'espace supplémentaire.
Le tri par tas est-il stable ?
Non. L'opération de descente peut déplacer des éléments égaux l'un par-dessus l'autre, si bien que le tri par tas ne préserve pas l'ordre relatif des clés égales.
Quand devrais-je utiliser le tri par tas ?
Utilisez le tri par tas lorsque vous avez besoin d'un pire cas garanti en O(n log n) avec seulement O(1) de mémoire supplémentaire. Il évite le risque de O(n²) du tri rapide sans le tampon en O(n) du tri fusion, au prix de la stabilité et de la performance de cache.
Quelle est la différence entre le tri par tas et le tri rapide ?
Les deux trient sur place, mais le tri rapide a un pire cas en O(n²) tandis que le tri par tas garantit O(n log n). En pratique le tri rapide est généralement plus rapide grâce à une meilleure localité de cache et moins d'échanges, si bien que le tri par tas est surtout préféré lorsque la borne du pire cas doit être garantie.
Quel est le lien entre le tri par tas et une file de priorité ?
Un tas binaire est l'implémentation standard d'une file de priorité, et le tri par tas revient essentiellement à extraire à plusieurs reprises le maximum de cette file. Si vous conservez déjà vos données dans un tas, en extraire les éléments un par un vous donne un ordre trié gratuitement.
Le tri par tas nécessite-t-il un max-heap ou un min-heap ?
Pour trier en ordre croissant sur place, utilisez un max-heap : le plus grand élément est échangé à la fin à chaque passe, faisant croître la queue triée depuis la droite. Un min-heap produirait un ordre décroissant sur place, ou croissant si vous extrayez dans un tableau séparé.
Coddy programming languages illustration

Maîtrisez les algorithmes avec Coddy

COMMENCER