Avec le code suivant, on génère une liste au hasard puis on transforme cette liste en tas max.
from random import randint
import heapq
L = [randint(10,99) for _ in range(randint(7,17))]
print("Liste au hasard : ", L)
heapq._heapify_max(L)
print("Liste entassée :", L)
Quelques résultats :
Liste au hasard : [39, 77, 64, 14, 89, 86, 58, 85] Liste entassée : [89, 85, 86, 39, 77, 64, 58, 14]
Liste au hasard : [63, 69, 67, 57, 63, 57, 59, 53, 75] Liste entassée : [75, 69, 67, 63, 63, 57, 59, 53, 57]
Liste au hasard : [32, 58, 10, 79, 77, 18, 44, 26, 14, 92, 35, 53, 50, 60, 29] Liste entassée : [92, 79, 60, 32, 77, 53, 44, 26, 14, 58, 35, 18, 50, 10, 29]
Sauriez vous déterminer quelle propriété guide la formation de la version entassée ? (sans chercher à détailler comment l'on passe de la liste à la liste entassée : ce sera l'objectif du paragraphe suivant.)
- Indication
- Définition du tas max
- passage de l'arbre à la liste
- passage de la liste à l'arbre
La représentation suivante des listes (entassées) vous mettra sur la piste de la définition d'un tas max.
- Représentation de [89, 85, 86, 39, 77, 64, 58, 14] :
- Représentation de [75, 69, 67, 63, 63, 57, 59, 53, 57] :
- Représentation de [92, 79, 60, 32, 77, 53, 44, 26, 14, 58, 35, 18, 50, 10, 29] :
- Il s'agit d'un arbre binaire (chaque noeud a au plus deux fils : un fils gauche et un fils droit).
- Chaque niveau est complet, sauf peut-être le dernier. Si le dernier niveau n'est pas complet, les noeuds de ce niveau sont le plus à gauche possible.
- Chaque noeud contient une valeur au plus égale à celle de son parent.
La racine de l'arbre contient donc la plus grande des valeurs inscrites dans les noeuds.
A partir de l'arbre, on retrouve la liste (entassée) avec les relations suivantes :
- La racine de l'arbre est l'élément d'indice 0 dans la liste.
- Le fils droit de l'élément d'indice i dans la liste est l'élément d'indice 2i+1.
- Le fils gauche de l'élément d'indice i dans la liste est l'élément d'indice 2i+2.
- Le parent de l'élément d'indice i de la liste est \( \lceil \frac{i}{2}-1 \rceil\) (où \( \lceil \ \ \rceil\) est la fonction partie entière supérieure).
- On peut également ajouter que l'élément de la liste ayant pour indice len(liste)-1 (c'est à dire le dernier élément de la liste) est la feuille de l'arbre se trouvant au niveau le plus bas de l'arbre (où "bas" est relatif à la représentation classique plaçant la racine en haut !) et le plus à droite.
Le plus grand élément de la liste entassée se trouve à l'indice 0.
Pour construire l'arbre à partir de la liste entassée : on lit les éléments de la liste dans l'ordre des indices et on crée les noeuds de haut en bas et de gauche à droite au fur et à mesure de cette lecture de la liste.
Il nous restera bien sûr à déterminer comment l'on passe de la liste initiale à la liste entassée !