139 lines
3.3 KiB
C
139 lines
3.3 KiB
C
|
|
#include "binheap.h"
|
||
|
|
|
||
|
|
/*************************/
|
||
|
|
/* Fonctions auxiliaires */
|
||
|
|
/*************************/
|
||
|
|
|
||
|
|
/* La fonction de comparaison pour les tas d'entiers */
|
||
|
|
bool fcmp_int(void *x, void *y) {
|
||
|
|
return *(int *)x < *(int *)y;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Fonctions de navigation dans un arbre représenté par un tableau */
|
||
|
|
int left_binheap(int i) {
|
||
|
|
return i*2+1;
|
||
|
|
}
|
||
|
|
int right_binheap(int i) {
|
||
|
|
return i*2+2;
|
||
|
|
}
|
||
|
|
int parent_binheap(int i) {
|
||
|
|
return (i-1)/2;
|
||
|
|
}
|
||
|
|
bool isvalid_binheap(binheap *p, int i) {
|
||
|
|
return i < p->size_heap;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Modification de la taille du tableau */
|
||
|
|
static void grow_binheap(binheap *p) {
|
||
|
|
p->size_array *= 2;
|
||
|
|
p->array = realloc(p->array, p->size_array * sizeof(void *));
|
||
|
|
if (p->array == NULL) {
|
||
|
|
ERROR("Erreur d'allocation mémoire\n");
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void shrink_binheap(binheap *p) {
|
||
|
|
p->size_array /= 2;
|
||
|
|
p->array = realloc(p->array, p->size_array * sizeof(void *));
|
||
|
|
if (p->array == NULL) {
|
||
|
|
ERROR("Erreur d'allocation mémoire\n");
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/************************/
|
||
|
|
/* Fonctions primitives */
|
||
|
|
/************************/
|
||
|
|
|
||
|
|
/* Création d'un tas vide */
|
||
|
|
binheap *create_binheap(bool (*fc)(void *, void *)) {
|
||
|
|
binheap *p = malloc(sizeof(binheap));
|
||
|
|
if (p == NULL) {
|
||
|
|
ERROR("Erreur d'allocation mémoire\n");
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
p->array = malloc(1 * sizeof(void *));
|
||
|
|
if (p->array == NULL) {
|
||
|
|
ERROR("Erreur d'allocation mémoire\n");
|
||
|
|
exit(EXIT_FAILURE);
|
||
|
|
}
|
||
|
|
p->size_array = 1;
|
||
|
|
p->size_heap = 0;
|
||
|
|
p->fc = fc;
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Suppression */
|
||
|
|
void delete_binheap(binheap *p) {
|
||
|
|
if (p != NULL) {
|
||
|
|
if (p->array != NULL) {
|
||
|
|
free(p->array);
|
||
|
|
}
|
||
|
|
free(p);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Test du vide */
|
||
|
|
bool isempty_binheap(binheap *p) {
|
||
|
|
return p == NULL || p->size_heap == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Récupération de la taille */
|
||
|
|
int getsize_binheap(binheap *p) {
|
||
|
|
return p->size_heap;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Insertion d'une valeur */
|
||
|
|
void push_binheap(binheap *p, void *val) {
|
||
|
|
if (p->size_heap == p->size_array) {
|
||
|
|
grow_binheap(p);
|
||
|
|
}
|
||
|
|
p->array[p->size_heap] = val;
|
||
|
|
p->size_heap++;
|
||
|
|
int i = p->size_heap - 1;
|
||
|
|
while (i > 0 && p->fc(p->array[i], p->array[parent_binheap(i)])) {
|
||
|
|
void *temp = p->array[i];
|
||
|
|
p->array[i] = p->array[parent_binheap(i)];
|
||
|
|
p->array[parent_binheap(i)] = temp;
|
||
|
|
i = parent_binheap(i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Récupération du minimum sans le retirer */
|
||
|
|
void *peekmin_binheap(binheap *p) {
|
||
|
|
if (isempty_binheap(p)) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
return p->array[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Récupération du minimum en le retirant */
|
||
|
|
void *popmin_binheap(binheap *p) {
|
||
|
|
if (isempty_binheap(p)) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
void *min = p->array[0];
|
||
|
|
p->size_heap--;
|
||
|
|
p->array[0] = p->array[p->size_heap];
|
||
|
|
int i = 0;
|
||
|
|
while (isvalid_binheap(p, left_binheap(i))) {
|
||
|
|
int j = left_binheap(i);
|
||
|
|
if (isvalid_binheap(p, right_binheap(i)) && p->fc(p->array[right_binheap(i)], p->array[j])) {
|
||
|
|
j = right_binheap(i);
|
||
|
|
}
|
||
|
|
if (p->fc(p->array[j], p->array[i])) {
|
||
|
|
void *temp = p->array[i];
|
||
|
|
p->array[i] = p->array[j];
|
||
|
|
p->array[j] = temp;
|
||
|
|
i = j;
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (p->size_heap < p->size_array / 4) {
|
||
|
|
shrink_binheap(p);
|
||
|
|
}
|
||
|
|
return min;
|
||
|
|
}
|