update tp-huffman
This commit is contained in:
49
tp-huffman/Makefile
Normal file
49
tp-huffman/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
# CC=gcc or clang or gcc-14 (on OSX)
|
||||
CC=gcc
|
||||
|
||||
# Math, big numbers and SDL2 fonts
|
||||
LDLIBS=-lm
|
||||
|
||||
# The DEBUG_LEVEL (OFF, CRITICAL, ERROR, WARNING, INFO, TRACE)
|
||||
# is set by default to WARNING in error.h.
|
||||
# To set it on the command line, force compilation and set it.
|
||||
# Example: make -B CFLAGS="-DDEBUG_LEVEL=INFO" to see all debug messages
|
||||
# above the 'INFO' level.
|
||||
|
||||
# clang 14.0.3 does implement the C23 feature __VA_OPTS__ but issues a spurious
|
||||
# warning. The -Wno-gnu-zero-variadic-macro-arguments disables this warning.
|
||||
# This flag is ignored by gcc (which implements __VA_OPTS__ without any warning).
|
||||
ifeq ($(shell uname -s), Darwin)
|
||||
override CFLAGS += -std=gnu2x -MMD -Wall -pedantic -Wextra -Wshadow -Wpointer-arith \
|
||||
-Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wno-gnu-zero-variadic-macro-arguments
|
||||
endif
|
||||
|
||||
ifeq ($(shell uname -s), Linux)
|
||||
override CFLAGS += -std=gnu2x -MMD -Wall -pedantic -Wextra -Wshadow -Wpointer-arith \
|
||||
-Wcast-qual -Wstrict-prototypes -Wmissing-prototypes
|
||||
endif
|
||||
|
||||
SOURCES := $(wildcard *.c)
|
||||
OBJECTS := $(SOURCES:%.c=%.o)
|
||||
DEPS := $(SOURCES:%.c=%.d)
|
||||
OBJECTS_NO_SOURCE = dequeue.o
|
||||
|
||||
# Compilation in debug mode by default, to use gdb and valgrind. Warnings produce an error.
|
||||
all: CFLAGS += -g -O0 -Werror -Wno-unused-parameter -Wno-unused-function
|
||||
all: tp
|
||||
|
||||
# Once the program works, optimized mode (and no error in case of warning).
|
||||
nowerror: CFLAGS += -O3 -Wunused-parameter
|
||||
nowerror: tp
|
||||
|
||||
# Add parser.o scan.o if bison/flex interface.
|
||||
tp: $(OBJECTS) $(OBJECTS_NO_SOURCE)
|
||||
$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^ $(LDLIBS)
|
||||
|
||||
# Include dependancies generated by gcc -MMD.
|
||||
-include $(DEPS)
|
||||
|
||||
# Clean all.
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(DEPS) tp TAGS core
|
||||
19
tp-huffman/alloc.c
Normal file
19
tp-huffman/alloc.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file alloc.c
|
||||
* @brief Fonctions d'allocation mémoire.
|
||||
*/
|
||||
|
||||
#include "alloc.h"
|
||||
|
||||
void check_null(const char *function, char *file, int line, int n, ...) {
|
||||
va_list ap;
|
||||
char *s;
|
||||
|
||||
va_start(ap, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
void *p = va_arg(ap, void *);
|
||||
s = va_arg(ap, char *);
|
||||
if (p == NULL)
|
||||
PRINT_ERROR(KO, "CRITICAL", function, file, line, "%s is NULL.", s);
|
||||
}
|
||||
}
|
||||
1
tp-huffman/alloc.d
Normal file
1
tp-huffman/alloc.d
Normal file
@@ -0,0 +1 @@
|
||||
alloc.o: alloc.c alloc.h error.h
|
||||
182
tp-huffman/alloc.h
Normal file
182
tp-huffman/alloc.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @file alloc.h
|
||||
* @brief Macros et fonctions d'allocation mémoire.
|
||||
*
|
||||
* @details Les macros MALLOC(), CALLOC() et REALLOC() définies dans ce fichier
|
||||
* permettent d'allouer de la mémoire dynamiquement, en vérifiant que
|
||||
* l'allocation a réussi. En cas d'échec, elles affichent un message d'erreur
|
||||
* sur la sortie erreur, en indiquant la fonction, le fichier et la ligne où
|
||||
* l'allocation a échoué, et quittent le programme.
|
||||
*
|
||||
* La fonction multiple_free() permet de libérer plusieurs pointeurs en
|
||||
* un seul appel (mais attention, aucun de ces pointeurs ne doit être `NULL`, et
|
||||
* tous doivent avoir été alloués dynamiquement avant cette libération).
|
||||
*
|
||||
* La macro CHECK_NULL() permet de vérifier qu'un ou plusieurs pointeurs ne sont
|
||||
* pas `NULL`.
|
||||
*
|
||||
* La fonction check_null() n'est pas destinée à être utilisée directement, mais
|
||||
* est utilisée par la macro CHECK_NULL().
|
||||
*/
|
||||
|
||||
#ifndef ALLOC_H_
|
||||
#define ALLOC_H_
|
||||
|
||||
#include "error.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Macro pour allouer de la mémoire en utilisant la fonction malloc().
|
||||
* @param p Pointeur à allouer.
|
||||
* @param num_objects Nombre d'objets à allouer.
|
||||
*
|
||||
* @details
|
||||
* Alloue de la mémoire permettant de stocker `num_objects`, chacun de type
|
||||
* `*p`.
|
||||
*
|
||||
* **Exemple d'utilisation :**
|
||||
* ```
|
||||
* backmove *p;
|
||||
* MALLOC(p, 10); // Alloue un tableau de 10 backmove.
|
||||
* ```
|
||||
*
|
||||
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
|
||||
*
|
||||
* @attention
|
||||
* Le pointeur `p` doit avoir été déclaré, mais ne pas pointer vers une zone
|
||||
* déjà allouée dynamiquement (sous peine de créer une fuite mémoire).
|
||||
* Si `p` pointe déjà vers une zone allouée dynamiquement, il faut utiliser
|
||||
* REALLOC.
|
||||
*
|
||||
* @see REALLOC()
|
||||
*/
|
||||
|
||||
#define MALLOC(p, num_objects) \
|
||||
do { \
|
||||
void *tmp = malloc(sizeof *(p) * (num_objects)); \
|
||||
if (!tmp) { \
|
||||
FATAL("Malloc error."); \
|
||||
} \
|
||||
(p) = tmp; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Macro pour allouer de la mémoire en utilisant la fonction calloc().
|
||||
* @param p Pointeur à allouer.
|
||||
* @param num_objects Nombre d'objets à allouer.
|
||||
*
|
||||
* @details
|
||||
* Alloue de la mémoire initialisée à 0, permettant de stocker `num_objects`,
|
||||
* chacun de type `*p`.
|
||||
*
|
||||
* **Exemple d'utilisation :**
|
||||
* ```
|
||||
* backmove *p;
|
||||
* CALLOC(p, 10); // Alloue un tableau de 10 backmove, initialisé à 0.
|
||||
* ```
|
||||
*
|
||||
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
|
||||
*
|
||||
* @attention
|
||||
* Le pointeur `p` doit avoir été déclaré, mais ne pas pointer vers une zone
|
||||
* déjà allouée dynamiquement (sous peine de créer une fuite mémoire).
|
||||
* Si `p` pointe déjà vers une zone allouée dynamiquement, il faut utiliser
|
||||
* REALLOC.
|
||||
*
|
||||
* @sa REALLOC()
|
||||
*/
|
||||
|
||||
#define CALLOC(p, num_objects) \
|
||||
do { \
|
||||
void *tmp = calloc((num_objects), sizeof *(p)); \
|
||||
if (!tmp) { \
|
||||
FATAL("Calloc error."); \
|
||||
} \
|
||||
(p) = tmp; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/**
|
||||
* @brief Macro pour réallouer de la mémoire en utilisant la fonction realloc().
|
||||
* @param p Pointeur à allouer.
|
||||
* @param num_objects Nouveau nombre d'objets à allouer.
|
||||
*
|
||||
* Ré-alloue la mémoire pointée par un pointeur p, dont la valeur doit avoir été
|
||||
* retournée précédemment par une fonction d'allocation dynamique (malloc,
|
||||
* calloc, realloc ou une des macros de ce fichier).
|
||||
*
|
||||
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
|
||||
*
|
||||
* **Exemple d'utilisation :**
|
||||
* ```
|
||||
* backmove *p;
|
||||
* MALLOC(p, 10); // Alloue un tableau de 10 backmove.
|
||||
* // ...
|
||||
* REALLOC(p, 20); // Ré-alloue un tableau de 20 backmove en copiant le tableau
|
||||
* // précédent en début ce nouveay tableau, et affecte à p
|
||||
* // l'adresse de la première case de ce tableau.
|
||||
* ```
|
||||
*
|
||||
* Si l'allocation échoue, affiche un message d'erreur et quitte le programme.
|
||||
*
|
||||
* @attention
|
||||
* Le pointeur `p` doit avoir été déclaré et pointer vers une zone
|
||||
* déjà allouée dynamiquement.
|
||||
*
|
||||
* @sa MALLOC(), CALLOC()
|
||||
*/
|
||||
|
||||
#define REALLOC(p, num_objects) \
|
||||
do { \
|
||||
void *tmp = realloc((p), sizeof *(p) * (num_objects)); \
|
||||
if (!tmp) { \
|
||||
FATAL("Realloc error."); \
|
||||
} \
|
||||
(p) = tmp; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Macro permettant de tester si un ou plusieurs pointeurs sont NULL.
|
||||
* @param n Nombre de pointeurs à tester.
|
||||
* @param ... Pointeurs à tester, en alternance avec des chaînes de caractères.
|
||||
*
|
||||
* Il doit y avoir un pointeur à tester pour chaque chaîne de caractères, et
|
||||
* inversement.
|
||||
*
|
||||
* La chaîne de caractères qui suit chaque pointeur permet de personnaliser le
|
||||
* message d'erreur.
|
||||
*
|
||||
* @details
|
||||
* **Exemple d'utilisation :**
|
||||
* ```
|
||||
* CHECK_NULL(3, p1, "Name1", p2, "Name2", p3, "Name3");
|
||||
* ```
|
||||
* Ici, 3 est le nombre de pointeurs à vérifier, et p1, p2, p3 sont les
|
||||
* pointeurs. Si `p1` et `p3` sont NULL, la macro affichera un message d'erreur
|
||||
* de la forme :
|
||||
***
|
||||
[CRITICAL] Name1 is NULL!\n
|
||||
[CRITICAL] Name3 is NULL!
|
||||
***
|
||||
* @sa check_null()
|
||||
*/
|
||||
|
||||
#define CHECK_NULL(n, ...) \
|
||||
check_null \
|
||||
(__func__, __FILE__, __LINE__, \
|
||||
n __VA_OPT__( , ) __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Ne pas utiliser cette fonction directement, mais à la place la macro
|
||||
* ::CHECK_NULL(), qui indique dans le message la position de l'erreur dans le
|
||||
* source.
|
||||
*
|
||||
* @sa CHECK_NULL()
|
||||
*/
|
||||
|
||||
void check_null(const char *function, char *file, int line, int n, ...);
|
||||
|
||||
#endif // ALLOC_H_
|
||||
BIN
tp-huffman/alloc.o
Normal file
BIN
tp-huffman/alloc.o
Normal file
Binary file not shown.
138
tp-huffman/binheap.c
Normal file
138
tp-huffman/binheap.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#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;
|
||||
}
|
||||
1
tp-huffman/binheap.d
Normal file
1
tp-huffman/binheap.d
Normal file
@@ -0,0 +1 @@
|
||||
binheap.o: binheap.c binheap.h alloc.h error.h
|
||||
82
tp-huffman/binheap.h
Normal file
82
tp-huffman/binheap.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/************************************************************************/
|
||||
/** Files de priorité: implémentation d'une tas binaire par un tableau **/
|
||||
/************************************************************************/
|
||||
|
||||
#ifndef BINHEAP_H_
|
||||
#define BINHEAP_H_
|
||||
|
||||
#include "alloc.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// On travaille avec des tas génériques: le type des valeurs n'est pas fixé
|
||||
// Pour ce faire, les éléments du tas seront des pointeurs génériques (void *).
|
||||
// Le tas ne contiendra donc pas directement les valeurs mais des pointeurs
|
||||
// sur celles-ci.
|
||||
//
|
||||
// Puisque le type des valeurs n'est pas fixé, la fonction de comparaison qui
|
||||
// sert à ordonner les éléments du tas est un paramètre de ce tas. On utilise
|
||||
// pour cela des pointeurs de fonctions: un des champs du type sera un pointeur
|
||||
// sur une fonction qui associe un Booléen à deux éléments de type void * (qui
|
||||
// indique si le premier est considéré comme "plus petit" que le deuxième).
|
||||
|
||||
typedef struct {
|
||||
// Tableau stockant des pointeurs vers chaque valeur du tas
|
||||
void **array;
|
||||
// Taille totale du tableau
|
||||
int size_array;
|
||||
// Taille du tas (nombres de case utilisées dans le tableau)
|
||||
int size_heap;
|
||||
// Pointeur sur la fonction de comparaison utilisée par le tas
|
||||
bool (*fc)(void *, void *);
|
||||
} binheap;
|
||||
|
||||
/*************************/
|
||||
/* Fonctions auxiliaires */
|
||||
/*************************/
|
||||
|
||||
/* La fonction de comparaison pour les tas d'entiers */
|
||||
bool fcmp_int(void *x, void *y);
|
||||
// Déjà écrite dans binheap.c
|
||||
|
||||
/* Fonctions de navigation dans un arbre représenté par un tableau */
|
||||
int left_binheap(int i);
|
||||
// Retourne l'indice du fils gauche du noeud à l'indice i
|
||||
int right_binheap(int i); // Fils droit
|
||||
// Retourne l'indice du fils droit du noeud à l'indice i
|
||||
int parent_binheap(int i); // Parent
|
||||
// Retourne l'indice du parent du noeud à l'indice i
|
||||
bool isvalid_binheap(binheap *p, int i);
|
||||
// Teste si l'indice i correspond à un noeud est valide dans le tas p
|
||||
|
||||
/************************/
|
||||
/* Fonctions primitives */
|
||||
/************************/
|
||||
|
||||
/* Création d'un tas vide */
|
||||
binheap *create_binheap(bool (*)(void *, void *));
|
||||
// Le paramètre est un pointeur de fonction
|
||||
// Il faut lui donner l'adresse de la fonction de comparaison à utiliser
|
||||
// Par exemple, pour créer un tas d'entier on appellera la primitive avec
|
||||
// l'adresse de la fonction fcmp_int ci-dessus:
|
||||
// p = create_binheap(&fcmp_int);
|
||||
|
||||
/* Suppression */
|
||||
void delete_binheap(binheap *);
|
||||
|
||||
/* Test du vide */
|
||||
bool isempty_binheap(binheap *);
|
||||
|
||||
/* Taille */
|
||||
int getsize_binheap(binheap *);
|
||||
|
||||
/* Insertion d'une valeur */
|
||||
void push_binheap(binheap *, void *);
|
||||
|
||||
/* Récupération du minimum sans le retirer */
|
||||
void *peekmin_binheap(binheap *);
|
||||
|
||||
/* Récupération du minimum en le retirant */
|
||||
void *popmin_binheap(binheap *);
|
||||
|
||||
#endif
|
||||
BIN
tp-huffman/binheap.o
Normal file
BIN
tp-huffman/binheap.o
Normal file
Binary file not shown.
92
tp-huffman/dequeue.h
Normal file
92
tp-huffman/dequeue.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/******************************************************/
|
||||
/** Implémentation des tuyaux étendus par un tableau **/
|
||||
/******************************************************/
|
||||
|
||||
// Ce module permet de manipuler des tuyaux, et même en fait une extension du
|
||||
// type vu en cours d'algorithmique. En plus de pouvoir ajouter ou retirer un
|
||||
// élément à gauche ou à droite du tuyau, on peut aussi lire la i-ème valeur à
|
||||
// partir de la gauche ou de la droite (en revanche, on ne peut pas écrire "au
|
||||
// milieu" d'un tuyau). Voir les fonctions leftread et rightread.
|
||||
//
|
||||
// Ces tuyaux étendus sont implémentés par un tableau dynamique. Les fonctions
|
||||
// auxiliaires grow_dequeue et shrink_dequeue permettent de modifier la taille
|
||||
// du tableau en conséquence. La fonction print_dequeue permet d'afficher le
|
||||
// contenu du tuyau.
|
||||
//
|
||||
// Une version compilée Linux de ce module vous est fournie : dequeue.o.
|
||||
|
||||
#ifndef DEQUEUE_H_
|
||||
#define DEQUEUE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/**********************/
|
||||
/* Définition du type */
|
||||
/**********************/
|
||||
|
||||
typedef struct {
|
||||
int *array; // Tableau des valeurs
|
||||
int size_array; // Taille du tableau des valeurs
|
||||
int left; // Indice de la valeur à gauche du tuyau (si non-vide).
|
||||
int right; // Indice qui suit celui de la valeur à droite du tuyau (si
|
||||
// non-vide).
|
||||
bool empty; // Booléen indiquant si le tuyau est vide.
|
||||
} dequeue;
|
||||
|
||||
/*************************/
|
||||
/* Fonctions auxiliaires */
|
||||
/*************************/
|
||||
|
||||
// Double la taille du tableau utilisé dans la représentation.
|
||||
void grow_dequeue(dequeue *);
|
||||
|
||||
// Divise par deux la taille du tableau utilisé dans la représentation
|
||||
// (on supposera que seulement la moitié des cases sont utilisées dans
|
||||
// la représentation).
|
||||
void shrink_dequeue(dequeue *);
|
||||
|
||||
/************************/
|
||||
/* Fonctions primitives */
|
||||
/************************/
|
||||
|
||||
// Création
|
||||
dequeue *create_dequeue(void);
|
||||
|
||||
// Suppression
|
||||
void delete_dequeue(dequeue *);
|
||||
|
||||
// Taille
|
||||
int getsize_dequeue(dequeue *p);
|
||||
|
||||
// Test du vide
|
||||
bool isempty_dequeue(dequeue *);
|
||||
|
||||
// Insertion
|
||||
void leftinsert(int, dequeue *);
|
||||
void rightinsert(int, dequeue *);
|
||||
|
||||
// Lecture
|
||||
|
||||
// Les deux fonctions suivantes étendent le type abstrait tuyau vu en TD.
|
||||
// En effet, elles permettent de lire la i-ème valeur à partir de la gauche ou
|
||||
// de la droite, ce qui n'était pas possible avec le type abstrait tuyau.
|
||||
|
||||
// Lit la ième valeur en partant de la gauche (la première à gauche a pour
|
||||
// indice 0).
|
||||
int leftread(dequeue *, int i);
|
||||
|
||||
// Lit la ième valeur en partant de la droite (la première à droite a pour
|
||||
// indice 0).
|
||||
int rightread(dequeue *, int i);
|
||||
|
||||
// Suppression
|
||||
|
||||
int leftpull(dequeue *);
|
||||
|
||||
int rightpull(dequeue *);
|
||||
|
||||
// Affichage d'un tuyau
|
||||
// Cette primitive est déjà écrite. Utilisez-la pour vos tests.
|
||||
void print_dequeue(dequeue *p);
|
||||
|
||||
#endif // DEQUEUE_H_
|
||||
1
tp-huffman/dequeue.o
Symbolic link
1
tp-huffman/dequeue.o
Symbolic link
@@ -0,0 +1 @@
|
||||
dequeue_x86-64.o
|
||||
BIN
tp-huffman/dequeue_arm64.o
Normal file
BIN
tp-huffman/dequeue_arm64.o
Normal file
Binary file not shown.
BIN
tp-huffman/dequeue_x86-64.o
Normal file
BIN
tp-huffman/dequeue_x86-64.o
Normal file
Binary file not shown.
58
tp-huffman/error.h
Normal file
58
tp-huffman/error.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef ERROR_H_
|
||||
#define ERROR_H_
|
||||
|
||||
#define ATTENTION "\xe2\x9d\x97"
|
||||
#define HINT "\xe2\x9c\xa8"
|
||||
#define OK "\xE2\x9C\x85"
|
||||
#define KO "\xE2\x9D\x8C"
|
||||
|
||||
// In X mode, all messages more severe than X are printed.
|
||||
// clang-format off
|
||||
enum debug_level {OFF, CRITICAL, ERROR, WARNING, INFO, DEBUG, TRACE};
|
||||
enum msg_level {CRITICAL_L, ERROR_L, WARNING_L, INFO_L, DEBUG_L, TRACE_L};
|
||||
// clang-format on
|
||||
|
||||
#ifndef DEBUG_LEVEL
|
||||
#define DEBUG_LEVEL INFO
|
||||
#endif
|
||||
|
||||
// __VA_OPTS__ requires C2x. Clang issues spurious warning.
|
||||
|
||||
#define PRINT_ERROR(symbol, name, function, file, line, msg, ...) \
|
||||
do { \
|
||||
fprintf(stderr, \
|
||||
"\n" symbol \
|
||||
" [" \
|
||||
name \
|
||||
"]" \
|
||||
" - Function %s (%s:%d) -\n " \
|
||||
msg "\n", \
|
||||
function, file, line \
|
||||
__VA_OPT__( , ) __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define FATAL(msg, ...) \
|
||||
do { \
|
||||
PRINT_ERROR(ATTENTION, "FATAL", __func__, __FILE__, __LINE__, msg __VA_OPT__( , ) __VA_ARGS__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_DEBUG(symbol, name, level, msg, ...) \
|
||||
do { \
|
||||
if ((int)DEBUG_LEVEL > (int)level) \
|
||||
PRINT_ERROR(symbol, name, __func__, __FILE__, __LINE__, msg __VA_OPT__( , ) __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define TRACE(msg, ...) PRINT_DEBUG(OK, "TRACE", TRACE_L, msg, __VA_ARGS__)
|
||||
|
||||
#define DEBUG(msg, ...) PRINT_DEBUG(HINT, "DEBUG", DEBUG_L, msg, __VA_ARGS__)
|
||||
|
||||
#define INFO(msg, ...) PRINT_DEBUG(HINT, "INFO", INFO_L, msg, __VA_ARGS__)
|
||||
|
||||
#define WARNING(msg, ...) PRINT_DEBUG(ATTENTION, "WARNING", WARNING_L, msg, __VA_ARGS__)
|
||||
|
||||
#define ERROR(msg, ...) PRINT_DEBUG(ATTENTION, "ERROR", ERROR_L, msg, __VA_ARGS__)
|
||||
|
||||
#define CRITICAL(msg, ...) PRINT_DEBUG(KO, "CRITICAL", CRITICAL_L, msg, __VA_ARGS__)
|
||||
|
||||
#endif // ERROR_H_
|
||||
59
tp-huffman/huffcomp.c
Normal file
59
tp-huffman/huffcomp.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/************************************/
|
||||
/** Codage de Huffman: Compression **/
|
||||
/************************************/
|
||||
|
||||
#include "huffcomp.h"
|
||||
|
||||
/**********************************/
|
||||
/* Fonctions manipulant les codes */
|
||||
/**********************************/
|
||||
|
||||
/* Construction du tableau des codes à partir de l'arbre de Huffman */
|
||||
huffcode **create_huffdict(huffnode *tree) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Suppression du tableau de code */
|
||||
void delete_huffdict(huffcode **dict) {
|
||||
// À écrire
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
/** Fonction pour la compression d'un fichier **/
|
||||
/***********************************************/
|
||||
|
||||
/* Écriture d'un unsigned int sur 4 octets dans un fichier */
|
||||
void write_size(FILE *output, unsigned int size) {
|
||||
// À écrire
|
||||
}
|
||||
|
||||
/* Insertion d'un code à droite d'un tuyau servant de tampon */
|
||||
void insert_code_in_buffer(dequeue *buffer, huffcode *code) {
|
||||
// À écrire
|
||||
}
|
||||
|
||||
/* Calcule l'octet correspondant aux 8 derniers éléments d'un tuyau servant de
|
||||
* tampon */
|
||||
int buffer_to_byte(dequeue *buffer) {
|
||||
// À écrire
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Procédure de compression */
|
||||
void compress_file(FILE *in, FILE *out) {
|
||||
/* Phase 1: calcul de la taille de l'arbre et du dictionnaire à partir du
|
||||
* fichier source */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 2: écriture de la taille du fichier original */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 3: écriture de l'arbre en représentation préfixe */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 4: écriture du codage */
|
||||
}
|
||||
2
tp-huffman/huffcomp.d
Normal file
2
tp-huffman/huffcomp.d
Normal file
@@ -0,0 +1,2 @@
|
||||
huffcomp.o: huffcomp.c huffcomp.h alloc.h error.h dequeue.h hufftree.h \
|
||||
binheap.h
|
||||
71
tp-huffman/huffcomp.h
Normal file
71
tp-huffman/huffcomp.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/************************************/
|
||||
/** Codage de Huffman: Compression **/
|
||||
/************************************/
|
||||
|
||||
#ifndef HUFFCOMP_H_
|
||||
#define HUFFCOMP_H_
|
||||
|
||||
#include "alloc.h"
|
||||
#include "dequeue.h"
|
||||
#include "hufftree.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/************************************************/
|
||||
/* Type utilisé pour stocker un code de Huffman */
|
||||
/************************************************/
|
||||
|
||||
// Type pour représenter un seul code
|
||||
typedef struct {
|
||||
// Le nombre de bits dans le code (un code n'aura jamais plus de 256 bits).
|
||||
unsigned char size;
|
||||
|
||||
// Le tableau qui stocke le code : les valeurs sont toutes 0 ou 1.
|
||||
unsigned char *code;
|
||||
} huffcode;
|
||||
|
||||
// Le dictionnaire contiendra tous les codes.
|
||||
// Il sera de type huffcode **, et pointera vers 256 cases.
|
||||
// Chacun de ses éléments sera donc de type huffcode *.
|
||||
// Pour les valeurs i ayant un code, la ième case contient ce code
|
||||
// Pour les valeurs i n'ayant pas de code (de fréquence nulle), la ième case
|
||||
// contient NULL.
|
||||
|
||||
/********************************************/
|
||||
/* Fonction de construction du dictionnaire */
|
||||
/********************************************/
|
||||
|
||||
// Construction du dictionnaire à partir de l'arbre de Huffman.
|
||||
huffcode **create_huffdict(huffnode *tree);
|
||||
|
||||
// Suppression du dictionnaire
|
||||
void delete_huffdict(huffcode **dict);
|
||||
|
||||
/***********************************************/
|
||||
/** Fonction pour la compression d'un fichier **/
|
||||
/***********************************************/
|
||||
|
||||
// Écriture d'un unsigned int sur 4 octets dans un fichier.
|
||||
// output doit être ouvert en écriture.
|
||||
void write_size(FILE *output, unsigned int size);
|
||||
|
||||
// Insertion de tous les bits d'un code à droite d'un tuyau tampon.
|
||||
// Le tuyau est supposé contenir une séquence de 0 et de 1.
|
||||
void insert_code_in_buffer(dequeue *buffer, huffcode *code);
|
||||
|
||||
// Calcule l'octet correspondant aux 8 premiers bits à gauche d'un tuyau tampon.
|
||||
|
||||
// Le tuyau est supposé contenir une séquence de bits (0 ou 1) de longueur au
|
||||
// moins 8 Les 8 bits lus doivent être supprimés du tuyau.
|
||||
int buffer_to_byte(dequeue *buffer);
|
||||
|
||||
// Fonction de compression du fichier input dans output.
|
||||
// input doit être ouvert en lecture.
|
||||
// output doit être ouvert en écriture.
|
||||
// Le fichier output devra contenir dans l'ordre :
|
||||
// 1) La taille de input codée sur 4 octets
|
||||
// 2) La sauvegarde de l'arbre de Huffman obtenu à partir de input.
|
||||
// 3) Le codage de input.
|
||||
void compress_file(FILE *input, FILE *output);
|
||||
|
||||
#endif
|
||||
BIN
tp-huffman/huffcomp.o
Normal file
BIN
tp-huffman/huffcomp.o
Normal file
Binary file not shown.
34
tp-huffman/huffdecomp.c
Normal file
34
tp-huffman/huffdecomp.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "huffdecomp.h"
|
||||
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
/** Fonctions pour la décompression d'un fichier **/
|
||||
/**************************************************/
|
||||
/**************************************************/
|
||||
|
||||
/* Lecture de la taille du fichier décompressé dans le fichier compressé */
|
||||
unsigned int read_size(FILE *in) {
|
||||
// À écrire
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Décodage d'une valeur à partir d'un arbre de Huffman
|
||||
int read_huffcode(FILE *in, dequeue *deq, huffnode *thetree) {
|
||||
// À écrire
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Décompression */
|
||||
void decompress_file(FILE *in, FILE *out) {
|
||||
/* Phase 1: lecture de la taille du fichier décompressé */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 2: lecture de l'arbre de Huffman */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 3: décodage */
|
||||
|
||||
// À écrire
|
||||
}
|
||||
2
tp-huffman/huffdecomp.d
Normal file
2
tp-huffman/huffdecomp.d
Normal file
@@ -0,0 +1,2 @@
|
||||
huffdecomp.o: huffdecomp.c huffdecomp.h alloc.h error.h dequeue.h \
|
||||
hufftree.h binheap.h
|
||||
40
tp-huffman/huffdecomp.h
Normal file
40
tp-huffman/huffdecomp.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**************************************/
|
||||
/** Codage de Huffman: Décompression **/
|
||||
/**************************************/
|
||||
|
||||
#ifndef HUFFDECOMP_H_
|
||||
#define HUFFDECOMP_H_
|
||||
|
||||
#include "alloc.h"
|
||||
#include "dequeue.h"
|
||||
#include "hufftree.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Lecture de la taille du fichier décompressé dans le fichier compressé.
|
||||
// Le fichier doit être ouvert en lecture.
|
||||
// La taille est codée sur les 4 premiers octets.
|
||||
unsigned int read_size(FILE *in);
|
||||
|
||||
// Lecture d'un code de Huffman à partir du buffer et du fichier compressé.
|
||||
// Le fichier doit être ouvert en lecture.
|
||||
//
|
||||
// Lit un code entier et retourne la valeur qui lui est associée par l'arbre de
|
||||
// Huffman.
|
||||
//
|
||||
// Tant que le buffer est non-vide, c'est dans celui-ci qu'on lit.
|
||||
//
|
||||
// Si le buffer est vide, on lit un octet dans le fichier pour insérer ses 8
|
||||
// bits dans le buffer.
|
||||
//
|
||||
// Le buffer est potentiellement non-vide à la fin de la lecture d'un code. Les
|
||||
// bits qui restent dans le buffer font partie du prochain code à lire.
|
||||
int read_huffcode(FILE *in, dequeue *deq, huffnode *thetree);
|
||||
|
||||
// Procédure de décompression.
|
||||
// Le flux in doit être ouvert en lecture.
|
||||
// Le flux out doit être ouvert en écriture.
|
||||
// Décompresse le fichier in et écrit la version décompressée dans out.
|
||||
void decompress_file(FILE *in, FILE *out);
|
||||
|
||||
#endif
|
||||
BIN
tp-huffman/huffdecomp.o
Normal file
BIN
tp-huffman/huffdecomp.o
Normal file
Binary file not shown.
85
tp-huffman/hufftree.c
Normal file
85
tp-huffman/hufftree.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "hufftree.h"
|
||||
|
||||
/************************************/
|
||||
/* Primitives des arbres de Huffman */
|
||||
/************************************/
|
||||
|
||||
/* Création d'une feuille */
|
||||
huffnode *create_huffleaf(int byte, int freq) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Fusion de deux arbres avec un nouveau noeud racine */
|
||||
huffnode *merge_hufftree(huffnode *pl, huffnode *pr) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Teste si un noeud est une feuille */
|
||||
bool isleaf_huffnode(huffnode *p) {
|
||||
// À écrire
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Retourne la valeur de l'octet correspondant à un noeud */
|
||||
int getbyte_huffnode(huffnode *p) {
|
||||
// À écrire
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Retournent les fils d'un noeud */
|
||||
|
||||
huffnode *getleft_huffnode(huffnode *p) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
huffnode *getright_huffnode(huffnode *p) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Libération d'un arbre */
|
||||
|
||||
void free_hufftree(huffnode *p) {
|
||||
// À écrire
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* Fonctions manipulant les arbres de Huffman */
|
||||
/**********************************************/
|
||||
|
||||
/* Comparaison de deux arbres */
|
||||
bool compare_hufftree(void *p1, void *p2) {
|
||||
// À écrire
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Création de l'arbre de Huffman à partir du fichier à compresser */
|
||||
huffnode *datafile_to_hufftree(FILE *input) {
|
||||
/* Phase 1: création du tableau de fréquences */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 2: intialisation de la file de priorité à partir du tableau de
|
||||
* fréquences */
|
||||
|
||||
// À écrire
|
||||
|
||||
/* Phase 3: création de l'arbre de Huffman à partir de la file de priorités */
|
||||
|
||||
// À écrire
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Écriture de l'arbre de Huffman dans le futur fichier compressé */
|
||||
void save_hufftree(huffnode *p, FILE *f) {
|
||||
// À écrire
|
||||
}
|
||||
|
||||
/* Lecture de l'arbre de Huffman dans le fichier compressé */
|
||||
huffnode *read_hufftree(FILE *f) {
|
||||
// À écrire
|
||||
return NULL;
|
||||
}
|
||||
1
tp-huffman/hufftree.d
Normal file
1
tp-huffman/hufftree.d
Normal file
@@ -0,0 +1 @@
|
||||
hufftree.o: hufftree.c hufftree.h alloc.h error.h binheap.h
|
||||
98
tp-huffman/hufftree.h
Normal file
98
tp-huffman/hufftree.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**************************************/
|
||||
/** Les arbres de Huffman **/
|
||||
/** Implémentation par des pointeurs **/
|
||||
/**************************************/
|
||||
|
||||
#ifndef HUFFTREE_H_
|
||||
#define HUFFTREE_H_
|
||||
|
||||
#include "alloc.h"
|
||||
#include "binheap.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*******************************************/
|
||||
/* Type utilisé pour les arbres de Huffman */
|
||||
/*******************************************/
|
||||
|
||||
// Chaque objet correspond à un noeud de l'arbre.
|
||||
// On identifie un arbre avec un pointeur vers son noeud racine.
|
||||
//
|
||||
// Cela explique pourquoi les fonctions manipulant les arbres prennent en
|
||||
// argument un pointeur vers un noeud, et que leur nom se termine soit par
|
||||
// _huffnode, soit par _hufftree.
|
||||
|
||||
typedef struct huffnode {
|
||||
// Fréquence
|
||||
int freq;
|
||||
|
||||
// Octet codé par le noeud (significatif seulement si le noeud est une
|
||||
// feuille)
|
||||
int byte;
|
||||
|
||||
// Enfant gauche (NULL si pas de fils gauche)
|
||||
struct huffnode *leftchild;
|
||||
|
||||
// Enfant droit (NULL si pas de fils droit)
|
||||
struct huffnode *rightchild;
|
||||
} huffnode;
|
||||
|
||||
/************************************/
|
||||
/* Primitives des arbres de Huffman */
|
||||
/************************************/
|
||||
|
||||
// Création d'une feuille.
|
||||
// Les paramètres servent à initialiser les champs byte et freq (dans cet
|
||||
// ordre).
|
||||
huffnode *create_huffleaf(int byte, int freq);
|
||||
|
||||
// Fusion de deux arbres non-vides en utilisant un nouveau noeud racine.
|
||||
// La fréquence du nouveau noeud sera la somme de celles de ses deux enfants
|
||||
// Le champ byte du nouveau noeud n'est pas significatif (car ce n'est pas une
|
||||
// feuille).
|
||||
huffnode *merge_hufftree(huffnode *pl, huffnode *pr);
|
||||
|
||||
// Teste si un arbre est réduit à une seule feuille.
|
||||
// On doit tester si les deux enfants du noeud racine sont NULL
|
||||
bool isleaf_huffnode(huffnode *p);
|
||||
|
||||
// Retourne la valeur de l'octet codé dans un noeud.
|
||||
// Ne doit être utilisé que sur les feuilles.
|
||||
int getbyte_huffnode(huffnode *p);
|
||||
|
||||
// Retourne les enfants gauche et droit d'un noeud.
|
||||
huffnode *getleft_huffnode(huffnode *p);
|
||||
huffnode *getright_huffnode(huffnode *p);
|
||||
|
||||
// Libération complète d'un arbre de Huffman.
|
||||
void free_hufftree(huffnode *p);
|
||||
|
||||
/**********************************************/
|
||||
/* Fonctions manipulant les arbres de Huffman */
|
||||
/**********************************************/
|
||||
|
||||
// Fonction de comparaison entre deux arbres de Huffman à utiliser pour le tas
|
||||
// binaire. Les deux paramètres sont donc donnés par des void *. Il faut les
|
||||
// convertir ces pointeurs de façon appropriée dans la fonction
|
||||
// compare_hufftree.
|
||||
//
|
||||
// Le plus petit de deux arbres est celui dont la racine a la plus petite
|
||||
// fréquence.
|
||||
bool compare_hufftree(void *p1, void *p2);
|
||||
|
||||
// Création de l'arbre de Huffman à partir du fichier à compresser.
|
||||
// Le fichier doit être ouvert en lecture.
|
||||
// L'algorithme est basé sur les files de priorités.
|
||||
huffnode *datafile_to_hufftree(FILE *input);
|
||||
|
||||
// Écriture de l'arbre de Huffman dans le futur fichier compressé.
|
||||
// Le fichier doit être ouvert en lecture.
|
||||
// On stocke l'arbre par une représentation préfixe.
|
||||
void save_hufftree(huffnode *p, FILE *output);
|
||||
|
||||
// Lecture de l'arbre de Huffman dans un fichier.
|
||||
// Le fichier doit être ouvert en lecture.
|
||||
// La tête de lecture doit être positionnée au début du codage de l'arbre.
|
||||
huffnode *read_hufftree(FILE *in);
|
||||
|
||||
#endif
|
||||
BIN
tp-huffman/hufftree.o
Normal file
BIN
tp-huffman/hufftree.o
Normal file
Binary file not shown.
312
tp-huffman/main.c
Normal file
312
tp-huffman/main.c
Normal file
@@ -0,0 +1,312 @@
|
||||
#include "alloc.h"
|
||||
#include "binheap.h"
|
||||
#include "error.h"
|
||||
#include "huffcomp.h"
|
||||
#include "huffdecomp.h"
|
||||
#include "hufftree.h"
|
||||
#include "testprint.h"
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void test_heap(int *tab, int size);
|
||||
|
||||
/********************************/
|
||||
/* Fonction main pour les tests */
|
||||
/********************************/
|
||||
|
||||
// clang-format off
|
||||
static struct option long_options[] = {
|
||||
{"help" , no_argument, NULL, 'h'},
|
||||
{"tree" , no_argument , NULL, 'T'},
|
||||
{"dict" , no_argument , NULL, 'D'},
|
||||
{"decomp" , no_argument, NULL, 'd'},
|
||||
{"heap" , optional_argument, NULL, 'H'},
|
||||
{"output" , required_argument, NULL, 'o'},
|
||||
{"seed" , required_argument, NULL, 's'},
|
||||
//
|
||||
{NULL, 0, NULL, 0}};
|
||||
// clang-format on
|
||||
|
||||
#define DEFAULT_HEAP_SIZE 10
|
||||
int size_heap = DEFAULT_HEAP_SIZE;
|
||||
int seed = -1;
|
||||
bool decompress_mode = false, test_binheap_mode = false, huffdict = false,
|
||||
hufftree = false;
|
||||
char *outfilename = NULL;
|
||||
|
||||
static void usage(char *progname) {
|
||||
printf("\nUsage: %s [options]\n\n", progname);
|
||||
printf("Options disponibles :\n"
|
||||
"\t--help ou -h :"
|
||||
"\n\t\tAffiche cette aide.\n"
|
||||
"\n"
|
||||
"\t--tree ou -T:"
|
||||
"\n\t\tAffiche l'arbre de Huffman en cas de compression (ce n'est pas "
|
||||
"fait par défaut).\n"
|
||||
"\n"
|
||||
"\t--dict ou -D:"
|
||||
"\n\t\tAffiche le dictionnaire en cas de compression (ce n'est pas "
|
||||
"fait par "
|
||||
"défaut).\n"
|
||||
"\n"
|
||||
"\t--heap=<entier>ou -H<entier>:"
|
||||
"\n\t\tTeste les fonctions de tas sur un tas de taille <entier> (%d "
|
||||
"par défaut).\n"
|
||||
"\n"
|
||||
"\t--output=<nom_fichier> ou -o<nom_fichier> :"
|
||||
"\n\t\tDéfinit le nom du fichier de sortie pour la décompression.\n"
|
||||
"\n"
|
||||
"\t--seed=<entier> ou -s<entier> :"
|
||||
"\n\t\tDéfinit la graine du générateur aléatoire pour générer un "
|
||||
"tableau.\n"
|
||||
"\n",
|
||||
DEFAULT_HEAP_SIZE);
|
||||
}
|
||||
|
||||
static void parse_argv(int argc, char *argv[]) {
|
||||
for (;;) {
|
||||
int c = getopt_long(argc, argv, "hTdDs:o:H::", long_options, NULL);
|
||||
if (c == -1)
|
||||
break; // fin de lecture des options
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case 'H':
|
||||
test_binheap_mode = true;
|
||||
size_heap = (optarg == NULL) ? DEFAULT_HEAP_SIZE : atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
seed = atoi(optarg);
|
||||
if (seed <= -1) {
|
||||
ERROR("La graine doit être positive\n");
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
decompress_mode = true;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
huffdict = true;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
hufftree = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
outfilename = strdup(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
parse_argv(argc, argv);
|
||||
|
||||
// Initialisation du générateur de nombres aléatoires
|
||||
// Voir man 3 srandom.
|
||||
if (seed == -1) {
|
||||
seed = time(NULL) % 1000;
|
||||
INFO("Pour rejouer avec les mêmes tirages aléatoires: %s --seed=%d",
|
||||
argv[0], seed);
|
||||
}
|
||||
srandom(seed);
|
||||
|
||||
// Vous pouvez ajouter des tests pour les tas binaires et les arbres de
|
||||
// Huffman.
|
||||
//
|
||||
// Pensez à utiliser les fonctions disponibles dans testprint.h
|
||||
// pour afficher les tas binaires et les arbres de Huffman
|
||||
|
||||
// printf("binheap null - \n"); print_binheap(NULL);
|
||||
// binheap *heap = create_binheap(fcmp_int);
|
||||
// print_binheap(heap);
|
||||
// int v10 = 10;
|
||||
// push_binheap(heap, &v10);
|
||||
// print_binheap(heap);
|
||||
// int v5 = 5;
|
||||
// push_binheap(heap, &v5);
|
||||
// print_binheap(heap);
|
||||
// int v7 = 7;
|
||||
// push_binheap(heap, &v7);
|
||||
// push_binheap(heap, &v7);
|
||||
// print_binheap(heap);
|
||||
// popmin_binheap(heap);
|
||||
// print_binheap(heap);
|
||||
// popmin_binheap(heap);
|
||||
// print_binheap(heap);
|
||||
|
||||
// Test de binheap. Dans ce cas, on ne fait pas de compression/décompression.
|
||||
if (test_binheap_mode) {
|
||||
INFO("TEST DES TAS BINAIRES");
|
||||
INFO("---------------------\n");
|
||||
int *array = random_array(size_heap, 100);
|
||||
|
||||
INFO("\nTableau avant tri:");
|
||||
print_array(array, size_heap);
|
||||
|
||||
test_heap(array, size_heap);
|
||||
|
||||
INFO("\nTableau après tri:");
|
||||
print_array(array, size_heap);
|
||||
free(array);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Ici, compression ou décompression.
|
||||
// La compression du fichier f est faite dans un fichier f.huff.
|
||||
// La décompression du fichier f.huff est faite dans le fichier f.
|
||||
|
||||
if (!decompress_mode) {
|
||||
// Compression : tous les arguments suivants de main sont considérés comme
|
||||
// des noms de fichiers à compresser.
|
||||
|
||||
for (int i = optind; i < argc; i++) {
|
||||
struct stat b;
|
||||
|
||||
if (stat(argv[i], &b) != 0) {
|
||||
ERROR("Impossible de calculer la taille du fichier \"%s\"", argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b.st_size == 0) {
|
||||
WARNING("Fichier \"%s\" de taille nulle", argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
INFO("Compression du fichier \"%s\" de taille %lld", argv[i],
|
||||
(long long)b.st_size);
|
||||
|
||||
FILE *infile = fopen(argv[i], "r");
|
||||
if (infile == NULL) {
|
||||
ERROR("Impossible d'ouvrir le fichier à compresser \"%s\"", argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
huffnode *t = datafile_to_hufftree(infile);
|
||||
|
||||
// Arbre de Huffman
|
||||
if (hufftree) {
|
||||
INFO("Arbre de Huffman");
|
||||
print_hufftree(t);
|
||||
}
|
||||
|
||||
huffcode **d = create_huffdict(t);
|
||||
if (huffdict) {
|
||||
INFO("Affichage du dictionnaire");
|
||||
print_huffdict(d);
|
||||
}
|
||||
|
||||
// Création éventuelle du nom de fichier de sortie
|
||||
if (outfilename == NULL) {
|
||||
MALLOC(outfilename, strlen(argv[i]) + 6);
|
||||
strcpy(outfilename, argv[i]);
|
||||
strcpy(outfilename + strlen(outfilename), ".huff");
|
||||
}
|
||||
|
||||
FILE *outfile = fopen(outfilename, "w");
|
||||
if (outfile == NULL) {
|
||||
ERROR("Impossible d'ouvrir le fichier de sortie \"%s\"", outfilename);
|
||||
continue;
|
||||
}
|
||||
|
||||
INFO("Fichier compressé -> \"%s\"", outfilename);
|
||||
|
||||
// Appel de la fonction de compression
|
||||
compress_file(infile, outfile);
|
||||
|
||||
free(outfilename);
|
||||
|
||||
// Fermeture des fichiers
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (decompress_mode) {
|
||||
// Décompression : tous les arguments suivants de main sont considérés comme
|
||||
// des noms de fichiers à décompresser.
|
||||
for (int i = optind; i < argc; i++) {
|
||||
FILE *infile = fopen(argv[i], "r");
|
||||
if (infile == NULL) {
|
||||
ERROR("Impossible d'ouvrir le fichier d'entrée à décompresser \"%s\"",
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
INFO("Décompression de %s", argv[i]);
|
||||
|
||||
// Création éventuelle du nom de fichier de sortie
|
||||
if (outfilename == NULL) {
|
||||
MALLOC(outfilename, strlen(argv[i]) + 8);
|
||||
strcpy(outfilename, argv[i]);
|
||||
strcpy(outfilename + strlen(outfilename), ".dehuff");
|
||||
}
|
||||
|
||||
// Ouverture du fichier de sortie
|
||||
FILE *outfile = fopen(outfilename, "w");
|
||||
if (outfile == NULL) {
|
||||
ERROR("Impossible d'ouvrir le fichier de sortie \"%s\"", outfilename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Appel de la fonction de décompression
|
||||
decompress_file(infile, outfile);
|
||||
|
||||
free(outfilename);
|
||||
|
||||
// Fermeture des fichiers
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Implémentation du tri par les tas
|
||||
void test_heap(int *tab, int size) {
|
||||
int i;
|
||||
int temp[size];
|
||||
for (i = 0; i < size; i++) {
|
||||
temp[i] = tab[i];
|
||||
}
|
||||
|
||||
binheap *p = create_binheap(&fcmp_int);
|
||||
|
||||
printf("\nTest de push_binheap");
|
||||
printf("\n********************\n\n");
|
||||
for (i = 0; i < size; i++) {
|
||||
printf("Push de %d\n", temp[i]);
|
||||
push_binheap(p, temp + i);
|
||||
print_binheap(p);
|
||||
}
|
||||
printf("\n");
|
||||
printf("\nTest de pop_binheap");
|
||||
printf("\n*******************\n\n");
|
||||
if (p == NULL) {
|
||||
WARNING("Essai de pop sur un tas NULL, rien ne se passe\n");
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < size; i++) {
|
||||
tab[i] = *(int *)popmin_binheap(p);
|
||||
printf("Élément supprimé: %d\n", tab[i]);
|
||||
print_binheap(p);
|
||||
}
|
||||
}
|
||||
2
tp-huffman/main.d
Normal file
2
tp-huffman/main.d
Normal file
@@ -0,0 +1,2 @@
|
||||
main.o: main.c alloc.h error.h binheap.h huffcomp.h dequeue.h hufftree.h \
|
||||
huffdecomp.h testprint.h
|
||||
BIN
tp-huffman/main.o
Normal file
BIN
tp-huffman/main.o
Normal file
Binary file not shown.
340
tp-huffman/testprint.c
Normal file
340
tp-huffman/testprint.c
Normal file
@@ -0,0 +1,340 @@
|
||||
#include "testprint.h"
|
||||
#include "alloc.h"
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BAR "-" // un tiret
|
||||
|
||||
typedef char *string;
|
||||
|
||||
// Type utilisé pour représenter les arbres de Huffman en utilisant
|
||||
// des tableaux (plus pratique pour écrire la fonction d'affichage)
|
||||
typedef struct {
|
||||
bool *array_af;
|
||||
int *array_val;
|
||||
int size;
|
||||
} arraytree;
|
||||
|
||||
// Affichage d'un tableau d'entiers
|
||||
void print_array(int *tab, int size) {
|
||||
int i;
|
||||
printf("{");
|
||||
for (i = 0; i < size - 1; i++) {
|
||||
printf("%d, ", tab[i]);
|
||||
}
|
||||
printf("%d}\n", tab[size - 1]);
|
||||
}
|
||||
|
||||
// Affichage d'un tableau de pointeurs sur des entiers
|
||||
void print_point_array(int **tab, int size) {
|
||||
int i;
|
||||
printf("{");
|
||||
for (i = 0; i < size - 1; i++) {
|
||||
printf("%d, ", *tab[i]);
|
||||
}
|
||||
printf("%d}\n", *tab[size - 1]);
|
||||
}
|
||||
|
||||
// Génération d'un tableau d'entiers aléatoire
|
||||
int *random_array(int size, int max) {
|
||||
int *array;
|
||||
MALLOC(array, size);
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
array[i] = random() % (max + 1);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Génération d'un tas à partir d'un tableau d'entiers
|
||||
binheap *array_to_binheap(int *array, int size) {
|
||||
binheap *heap = create_binheap(&fcmp_int);
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
push_binheap(heap, (void *)(array + i));
|
||||
}
|
||||
return heap;
|
||||
}
|
||||
|
||||
// Affiche n fois le même la chaîne s
|
||||
static void rule(int n, string s) {
|
||||
for (int i = 0; i < n; i++)
|
||||
printf("%s", s);
|
||||
}
|
||||
|
||||
// Affichage d'un tas binaire
|
||||
void print_binheap(binheap *p) {
|
||||
rule(10, BAR);
|
||||
printf("\n");
|
||||
|
||||
if (p == NULL) {
|
||||
printf("Trying to print a NULL tree\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int h = 0; // Calcul de la hauteur de l'arbre (=nombre de lignes)
|
||||
int j = p->size_heap;
|
||||
while (j > 0) {
|
||||
h++;
|
||||
j = j >> 1;
|
||||
}
|
||||
|
||||
int s = 1; // nombre de caractères avant le milieu du pattern
|
||||
int B = 1; // B = nombre de patterns dans la ligne
|
||||
j = 0; // j = nombre d'éléments déjà affichés
|
||||
int sons = 0;
|
||||
|
||||
int y;
|
||||
for (y = h - 1; y >= 0; y--, B <<= 1) {
|
||||
// On part du haut de l'arbre
|
||||
|
||||
int pm = (s + 1) * (1 << y) - 1;
|
||||
int lb = (s + 1) * (1 << (y - 1)) - 1;
|
||||
int ep = 2 * pm + 1 - 2 * s;
|
||||
|
||||
// ligne avec les éléments
|
||||
rule(pm - s, " ");
|
||||
for (int b = 0; b < B && (j < p->size_heap); b++) {
|
||||
// printf(" "); // cas pair
|
||||
printf("%03i ", ((int *)p->array[j])[0]);
|
||||
j++;
|
||||
if (b < B - 1)
|
||||
rule(ep - 1, " "); // -1 pour l'espace terminal
|
||||
}
|
||||
printf("\n");
|
||||
if (y == 0)
|
||||
break; // fini si dernière ligne d'éléments
|
||||
|
||||
// ligne avec les branchements
|
||||
rule(lb, " ");
|
||||
for (int b = 0; b < B; b++) {
|
||||
if (right_binheap(sons) < p->size_heap) {
|
||||
printf("┌");
|
||||
rule(lb, "─");
|
||||
printf("┴");
|
||||
rule(lb, "─");
|
||||
printf("┐");
|
||||
if (b < B - 1)
|
||||
rule(pm, " ");
|
||||
} else if (left_binheap(sons) < p->size_heap) {
|
||||
printf("┌");
|
||||
rule(lb, "─");
|
||||
printf("┘");
|
||||
if (b < B - 1)
|
||||
rule(pm + 2, " ");
|
||||
}
|
||||
sons++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
rule(10, BAR);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
// Affichage d'un arbre de Huffman
|
||||
static int maxoftwo(int a, int b) {
|
||||
if (a < b) {
|
||||
return b;
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
static int hufftree_maxsize(huffnode *n) {
|
||||
if (n == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
return 2 * maxoftwo(hufftree_maxsize(n->leftchild),
|
||||
hufftree_maxsize(n->rightchild)) +
|
||||
1;
|
||||
}
|
||||
}
|
||||
|
||||
static void hufftree_fillarray(huffnode *n, int *arrayval, bool *arraytv,
|
||||
int pos) {
|
||||
if (n != NULL) {
|
||||
arrayval[pos] = n->byte;
|
||||
arraytv[pos] = true;
|
||||
hufftree_fillarray(n->leftchild, arrayval, arraytv, 2 * pos + 1);
|
||||
hufftree_fillarray(n->rightchild, arrayval, arraytv, 2 * pos + 2);
|
||||
}
|
||||
}
|
||||
|
||||
static arraytree *hufftree_to_array(huffnode *n) {
|
||||
int size = hufftree_maxsize(n);
|
||||
// printf("%d\n",size);
|
||||
arraytree *new;
|
||||
MALLOC(new, 1);
|
||||
MALLOC(new->array_af, size);
|
||||
MALLOC(new->array_val, size);
|
||||
new->size = size;
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
new->array_af[i] = false;
|
||||
}
|
||||
hufftree_fillarray(n, new->array_val, new->array_af, 0);
|
||||
return new;
|
||||
}
|
||||
|
||||
void print_hufftree(huffnode *n) {
|
||||
arraytree *p = hufftree_to_array(n);
|
||||
|
||||
rule(10, BAR);
|
||||
printf("\n");
|
||||
|
||||
if (p == NULL) {
|
||||
WARNING("Essai d'affichage d'un arbre de Huffman NULL\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->size == 0) {
|
||||
WARNING("Essai d'affichage d'un arbre de Huffman vide\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->size == 1) {
|
||||
printf(" %c\n", n->byte);
|
||||
rule(10, BAR);
|
||||
printf("\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int h = 0; // Calcul de la hauteur de l'arbre (=nombre de lignes)
|
||||
int j = p->size;
|
||||
while (j > 0) {
|
||||
h++;
|
||||
j = j >> 1;
|
||||
}
|
||||
|
||||
int s = 0; // nombre de caractères avant le milieu du pattern
|
||||
int B = 1; // B = nombre de patterns dans la ligne
|
||||
j = 1; // j = nombre d'éléments déjà affichés
|
||||
int mine1 = 1;
|
||||
int sons = 0;
|
||||
|
||||
int y;
|
||||
for (y = h - 1; y >= 0; y--, B <<= 1) {
|
||||
// On part du haut de l'arbre
|
||||
|
||||
int pm = (s + 1) * (1 << y) - 1;
|
||||
int lb = (s + 1) * (1 << (y - 1)) - 1;
|
||||
int ep = 2 * pm + 1 - 2 * s;
|
||||
|
||||
// ligne avec les éléments
|
||||
if (y != h - 1) {
|
||||
rule(pm - s, " ");
|
||||
for (int b = 0; b < B && (mine1 < p->size); b++) {
|
||||
// printf(" "); // cas pair
|
||||
if (p->array_af[mine1] && mine1 % 2 == 1) {
|
||||
printf("│0");
|
||||
} else if (p->array_af[mine1] && mine1 % 2 == 0) {
|
||||
printf("│1");
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
mine1++;
|
||||
if (b < B - 1)
|
||||
rule(ep - 1, " "); // -1 pour l'espace terminal
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
rule(pm - s, " ");
|
||||
for (int b = 0; b < B && (j < p->size); b++) {
|
||||
// printf(" "); // cas pair
|
||||
if (p->array_af[j] && !p->array_af[2 * j + 1] &&
|
||||
!p->array_af[2 * j + 2]) {
|
||||
char thechar = (char)p->array_val[j];
|
||||
if (thechar == '\n') {
|
||||
printf("⏎ ");
|
||||
} else if (thechar == ' ') {
|
||||
printf("␠ ");
|
||||
} else {
|
||||
printf("%c ", (char)p->array_val[j]);
|
||||
}
|
||||
} else if (p->array_af[j]) {
|
||||
printf("│ ");
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
j++;
|
||||
if (b < B - 1)
|
||||
rule(ep - 1, " "); // -1 pour l'espace terminal
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (y == 0)
|
||||
break; // fini si dernière ligne d'éléments
|
||||
}
|
||||
|
||||
// ligne avec les branchements
|
||||
rule(lb, " ");
|
||||
for (int b = 0; b < B; b++) {
|
||||
if (p->array_af[2 * sons + 1] && p->array_af[2 * sons + 2]) {
|
||||
printf("┌");
|
||||
rule(lb, "─");
|
||||
printf("┴");
|
||||
rule(lb, "─");
|
||||
printf("┐");
|
||||
if (b < B - 1)
|
||||
rule(pm, " ");
|
||||
} else if (p->array_af[2 * sons + 1]) {
|
||||
printf("┌");
|
||||
rule(lb, "─");
|
||||
printf("┘");
|
||||
rule(lb + 1, " ");
|
||||
if (b < B - 1)
|
||||
rule(pm, " ");
|
||||
} else if (p->array_af[2 * sons + 2]) {
|
||||
rule(lb + 1, " ");
|
||||
printf("└");
|
||||
rule(lb, "─");
|
||||
printf("┐");
|
||||
if (b < B - 1)
|
||||
rule(pm, " ");
|
||||
|
||||
} else {
|
||||
rule(2 * lb + 3, " ");
|
||||
if (b < B - 1)
|
||||
rule(pm, " ");
|
||||
}
|
||||
sons++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
rule(10, BAR);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
/* Affichage d'un code de Huffman */
|
||||
void print_code(huffcode *e) {
|
||||
CHECK_NULL(2, e, "The code entry", e->code, "The array in the code entry");
|
||||
int i;
|
||||
for (i = 0; i < e->size; i++) {
|
||||
printf("%d", e->code[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Affichage d'un tableau de codes de Huffman */
|
||||
void print_huffdict(huffcode **codes) {
|
||||
int i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (codes[i] != NULL) {
|
||||
printf("Valeur: %3d ", i);
|
||||
if (i == '\n') {
|
||||
printf("ASCII: ⏎ Code: ");
|
||||
} else if (i == ' ') {
|
||||
printf("ASCII: ␠ Code: ");
|
||||
} else {
|
||||
printf("ASCII: %c Code: ", i);
|
||||
}
|
||||
print_code(codes[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
tp-huffman/testprint.d
Normal file
2
tp-huffman/testprint.d
Normal file
@@ -0,0 +1,2 @@
|
||||
testprint.o: testprint.c testprint.h alloc.h error.h binheap.h huffcomp.h \
|
||||
dequeue.h hufftree.h huffdecomp.h
|
||||
74
tp-huffman/testprint.h
Normal file
74
tp-huffman/testprint.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/******************************************/
|
||||
/******************************************/
|
||||
/** Fonctions d'affichage pour les tests **/
|
||||
/******************************************/
|
||||
/******************************************/
|
||||
|
||||
#ifndef TESTPRINT_H_
|
||||
#define TESTPRINT_H_
|
||||
|
||||
#include "alloc.h"
|
||||
#include "binheap.h"
|
||||
#include "huffcomp.h"
|
||||
#include "huffdecomp.h"
|
||||
#include "hufftree.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/************/
|
||||
/* Tableaux */
|
||||
/************/
|
||||
|
||||
// Affichage d'un tableau d'entiers.
|
||||
void print_array(int *tab, int size);
|
||||
|
||||
// Affichage d'un tableau de pointeurs sur des entiers.
|
||||
void print_point_array(int **tab, int size);
|
||||
|
||||
// Génération d'un tableau d'entiers aléatoire.
|
||||
// Les entiers générés sont compris entre 0 et max.
|
||||
int *random_array(int size, int max);
|
||||
|
||||
/****************/
|
||||
/* Tas binaires */
|
||||
/****************/
|
||||
|
||||
// Génération d'un tas à partir d'un tableau d'entiers.
|
||||
//
|
||||
// Attention, les éléments dans le tas seront des pointeurs vers
|
||||
// les éléments du tableau pris en entrée. Il ne faut donc plus
|
||||
// modifier les valeurs référencées par les pointeurs dans le
|
||||
// tableau (sous peine de casser le tas).
|
||||
binheap *array_to_binheap(int *array, int size);
|
||||
|
||||
// Affichage d'un tas binaire.
|
||||
//
|
||||
// Prévu pour un tas dont les éléments sont des pointeurs vers des entiers.
|
||||
// On peut en construire un avec les fonctions précédentes.
|
||||
// Attention à ne pas afficher des tas "trop gros". Ils sont trop larges
|
||||
// pour un terminal et les retours à la ligne rendent l'affichage illisible.
|
||||
void print_binheap(binheap *);
|
||||
|
||||
/*********************/
|
||||
/* Arbres de Huffman */
|
||||
/*********************/
|
||||
|
||||
// Affichage d'un arbre de Huffman.
|
||||
//
|
||||
// À nouveau, l'affichage n'est lisible que pour de "petits" arbres de Huffman.
|
||||
// Faites attention à tester vos fonctions sur des fichiers qui ne contiennent
|
||||
// pas beaucoup de caractères distincts (afin de minimiser la taille des
|
||||
// arbres).
|
||||
void print_hufftree(huffnode *);
|
||||
|
||||
/*******************/
|
||||
/* Code de Huffman */
|
||||
/*******************/
|
||||
|
||||
// Affichage d'un code de Huffman.
|
||||
void print_code(huffcode *e);
|
||||
|
||||
// Affichage d'un tableau de codes de Huffman.
|
||||
void print_huffdict(huffcode **dict);
|
||||
|
||||
#endif
|
||||
BIN
tp-huffman/testprint.o
Normal file
BIN
tp-huffman/testprint.o
Normal file
Binary file not shown.
BIN
tp-huffman/tp
Executable file
BIN
tp-huffman/tp
Executable file
Binary file not shown.
Reference in New Issue
Block a user