Un tas est caractérisé par sa longueur qui représente sa capacité (le nombre maximal d'élements qu'il peut contenir) et sa taille qui représente le nombre d'élement du tas. Il est dit borné si sa capacité est fixe comme dans notre cas.
En plus de la rapidité accrue, le langage C permet une meilleure gestion de la mémoire.
</p>
<h3style="color:##7C7C7C"> II- Représentation de la structure de donnée</h3>
<h4style="color:##7C7C7C"> 1- Noeud du tas</h4>
<p>
Un tas en général vérifie un certain nombre de caractéristques:
On a créé le noeud comme étant une structure "<i>struct node_s</i>" qui contient :
<ul>
<li>longueur du tas >= taille du tas</li>
<li>parent de l'élement numéro i est à la i/2 ème position</li>
<li>parent de l'élement numéro i est à la 2i ème position</li>
<li>parent de l'élement numéro i est à la 2i + 1 ème position</li>
<li>la clé du noeud</li>
<li>le degré du noeud</li>
<li>un pointeur sur le parent</li>
<li>un pointeur sur le frère à gauche</li>
<li>un pointeur sur le fils le plus à droite</li>
</ul>
</p>
<p>
Il faut noter qu'il existe deux type de tas, selon la proprieté fondamentale qu'il vérifie :
<ul>
<li>si parent de l'élement numéro i est inférieur au i ème élement, alors le tas est dit minimal.</li>
<li>si parent de l'élement numéro i est supérieur au i ème élement, alors le tas est dit maximal.</li>
</ul>
On a ensuite créé le type comme étant la structure du noeud "<i>node_t</i>".
Nous avons implémenter un benchmark qui effectue trois expériences différents sur les deux types de tas en même temps :
On a créé le tas comme étant une structure "<i>struct binomial_heap_s</i>" qui contient :
<ul>
<li>Ajout croissant : on ajoute n élements ordonnés dans l'ordre croissant allant de 1 jusqu'à n.</li>
<li>Ajout décroissant : on ajoute n élements ordonnés dans l'ordre décroissant allant de n jusqu'à 1.</li>
<li>Ajout aléatoire : on ajoute n élements NON-ordonnés compris entre 1 et n.</li>
<li>un pointeur vers le premier noeud du tas</li>
</ul>
</p>
<h3style="color:##7C7C7C"> III- Analyse des résultats des experiences</h3>
<h4style="color:##7C7C7C"> 1- Courbes de temps amorti</h4>
<p>
D'abord, on remarque l'analogie entre les courbes d'ajout croissant et décroissant. Analysons l'exemple des ajouts croissant :<br>
On remarque que le temps amorti pour les ajouts croissants dans un tas minimal est plus grand que celui du tas maximal. Ceci est dù au nombre de swap (permutations) dont la courbe sera analysée dans ce qui suit.
De plus on remarque un caractère asymptotique qui nous rappelle de la complexité temporelle devant être théoriquement O(log n) au pire et au meilleur des cas.
On a ensuite créé le type comme étant la structure du tas "<i>binomial_heap_t</i>".
</p>
<p>
Pour le cas d'ajout aléatoire on remarque une NON-régularité dans le tracé de la courbe ce qui est expliquable par les données de permutation. Cependant, on note une corrélation entre les courbes des tas minimal et maximal.
Il faut noter qu'on peut aussi utiliser le type "<i>node_t</i>" pour toutes les opérations puisque le tas n'est rien d'autre qu'une liste chainée des noeuds racines des arbres binomiaux.<br>
Cependant, on a préféré créer le type du tas afin de pouvoir différencier les appels des pointeurs dans le code.
</p>
<h4style="color:##7C7C7C"> 2- Courbes de mémoire gaspillée</h4>
<h3style="color:##7C7C7C"> III- Fonctions</h3>
<p>
Comme expliqué ci-dessus, dans notre cas nous avons implémenté un tas binaire borné. Ainsi, sion ajoute à chaque itération un élement, l'espace de mémoire libre décroit linéairement comme le mettent en évidence toutes les courbes.
Hormis le fait qu'on nous ait demandé d'implémenter les trois opérations de bases (fusion de tas, ajout de noeud et extraction du min), plusieurs autres fonctions sont créées afin de faciliter la lecture du code et son maintenance.
</p>
<h4style="color:##7C7C7C"> 3- Courbes de permutations (SWAP)</h4>
<h4style="color:##7C7C7C"> 1- Noeud du tas</h4>
<p>
Pour la courbe d'ajout croissant, on remarque que le nombre de swap est croissant pour le tas minimal et totalement absent pour le tas maximal (Aucune permutation n'est effectuée).
Cela est expliquable par le fait que l'ajout croissant vérifie la condition du tas max tel que le i ème élement est supérieur au i+1 ème élement.
Ainsi, chaque élement ajouté à la fin du tableau vérifie la proprieté de tas maximal (le i ème élement est supérieur au parent de celui-ci) à savoir qu'il est supérieur à son parent ce qui ne nécessite aucune permutation.<br>
Pour la courbe d'ajout décroissant, les mêmes caractéristiques sont remarquées avec un raisonnement inversé à savoir que le tas max est celui qui effectue le plus de permutation d'élements.<br>
De plus, on peut remarquer une caractéristique intéressante dans les deux cas à savoir que le nombre de permutations se stabilise pour 2<sup>k</sup> élements ajoutés (2, 4, 8, 16 ..).
Les fonctions suivantes agissent sur les noeuds ou sur des listes chainées (les arbres binomiaux) :
</p>
<p>
Pour la courbe aléatoire, la non régularité de la courbe est le resultat attendu. En effet, chaque fois que l'on ajoute un élement, on ne peut pas prédire le nombre de permutation à effectuer.
Cela est du à la dépendance de ce dernier de la position de l'element à ajouter.<br>
De plus, on peut dire que les deux types de tas possèdent le même comportement.
<ul>
<li> Fonction d'initialisation d'un noeud.
</li>
<li> Relie deux arbres binomiaux de même ordre (k-1).
</li>
<li>
Inverse la liste des enfants d'une racine.
</li>
<li>
Fonction de libération de la mémoire occupée par un noeud.
</li>
</ul>
</p>
<h4style="color:##7C7C7C"> 2- le Tas</h4>
<p>
Les fonctions suivantes agissent sur les tas :
</p>
<p>
<ul>
<li> Fonction d'initialisation d'un tas binomial (ne contenant aucun noeud).
</li>
<li> Fonction de libération de la mémoire occupée par un tas binomial.
</li>
<li>
Renvoie un poitnteur sur le noeud dont la clé est minimale.
</li>
<li>
Unir deux tas binomiaux.
</li>
<li>
Renvoie un poitnteur sur le noeud dont la clé est minimale et définit le pointeur du noeud qui le précède.
</li>
<li>
Insère un noeud dans le tas.
</li>
<li>
Extrait la noeud dont la clé est minimale du tas.
</li>
<li>
Fusionner les deux listes de racines (les tas h1 et h2)