Modification du type HufTree et implémentation lecture arbre

Utilisation de WriteBuffer et ReadBuffer et le type HufTree
n'est plus une structure mais un typedef vers HufVertex*
This commit is contained in:
Mattéo Delabre 2016-11-19 21:38:56 +01:00
parent e19860e544
commit 9576b371ce
2 changed files with 44 additions and 81 deletions

View File

@ -4,12 +4,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
typedef struct Buffer Buffer; typedef struct WriteBuffer WriteBuffer;
typedef struct ReadBuffer ReadBuffer;
/** /**
* Représente un des sommets d'un arbre de Huffman * Représente un des sommets d'un arbre de Huffman (représente l'arbre
* en entier s'il s'agit de la racine)
*/ */
typedef struct HufVertex HufVertex; typedef struct HufVertex HufVertex;
typedef HufVertex* HufTree;
struct HufVertex { struct HufVertex {
// Indique la fréquence d'apparition de la lettre du sommet // Indique la fréquence d'apparition de la lettre du sommet
// dans le corpus original, ou bien la somme des fréquences // dans le corpus original, ou bien la somme des fréquences
@ -28,18 +31,6 @@ struct HufVertex {
HufVertex* child_r; HufVertex* child_r;
}; };
/**
* Représente un arbre de Huffman
*/
typedef struct HufTree HufTree;
struct HufTree {
// Pointeur sur la racine de l'arbre
HufVertex* root;
// Quantité de sommets dans l'arbre
size_t size;
};
/** /**
* Construire un arbre de Huffman basé sur les fréquences * Construire un arbre de Huffman basé sur les fréquences
* de caractères passées dans `frequencies` * de caractères passées dans `frequencies`
@ -52,13 +43,13 @@ HufTree createTree(double* frequencies);
* Écrit une représentation binaire de l'arbre dans le * Écrit une représentation binaire de l'arbre dans le
* tampon passé en paramètre * tampon passé en paramètre
*/ */
void writeTree(HufTree, Buffer*); void writeTree(HufTree, WriteBuffer*);
/** /**
* Reconstruit un arbre de Huffman à partir du fichier passé * Reconstruit un arbre de Huffman à partir du fichier passé
* en paramètre * en paramètre
*/ */
HufTree readTree(FILE*); HufTree readTree(ReadBuffer*);
/** /**
* Libérer la mémoire occupée par un arbre de Huffman * Libérer la mémoire occupée par un arbre de Huffman

View File

@ -12,18 +12,6 @@
*/ */
static void _findMinimalVertices(HufVertex**, size_t, size_t* min, size_t* sec); static void _findMinimalVertices(HufVertex**, size_t, size_t* min, size_t* sec);
/**
* Écrit dans le tampon donné les informations sur le sommet
* en question et tous ses fils
*/
static void _writeVertex(HufVertex, Buffer*);
/**
* Libérer récursivement la mémoire occupée par le sommet
* donné ainsi que celle de tous ses enfants (s'il en a).
*/
static void _freeTreeVertex(HufVertex*);
/** /**
* Créer une nouvelle chaîne contenant la chaîne donnée * Créer une nouvelle chaîne contenant la chaîne donnée
* suffixée du caractère donné * suffixée du caractère donné
@ -105,14 +93,9 @@ HufTree createTree(double* frequencies) {
remaining_count--; remaining_count--;
} }
// Stockage de l'adresse vers la racine de l'arbre dans un HufTree.
// Il est désormais possible de désallouer `remaining`, car la seule // Il est désormais possible de désallouer `remaining`, car la seule
// connaissance de la racine permet de parcourir tout l'arbre // connaissance de la racine permet de parcourir tout l'arbre
HufTree tree = { HufTree tree = remaining[0];
.root = remaining[0],
.size = 2 * leaves_count - 1
};
free(remaining); free(remaining);
return tree; return tree;
} }
@ -147,66 +130,55 @@ void _findMinimalVertices(
} }
} }
void writeTree(HufTree tree, Buffer* buffer) { void writeTree(HufTree tree, WriteBuffer* buffer) {
_writeVertex(*tree.root, buffer); if (tree->child_l != NULL && tree->child_r != NULL) {
} // Bit "1" indiquant que le sommet a des enfants
putBuffer(1, buffer);
void _writeVertex(HufVertex vertex, Buffer* buffer) {
if (vertex.child_l != NULL && vertex.child_r != NULL) {
// Séquence de 9 bits indiquant un sommet qui
// n'est pas une feuille (100000000)
pushToBuffer(1, buffer);
for (int i = 0; i < 8; i++) {
pushToBuffer(0, buffer);
}
// Écriture du fils gauche et du fils droit // Écriture du fils gauche et du fils droit
_writeVertex(*vertex.child_l, buffer); writeTree(tree->child_l, buffer);
_writeVertex(*vertex.child_r, buffer); writeTree(tree->child_r, buffer);
} else { } else {
// Séquence de 9 bits encodant la feuille rencontrée // Bit "0" indiquant que le sommet n'a pas d'enfants
// (0 + octet du caractère) putBuffer(0, buffer);
pushToBuffer(0, buffer);
// Écriture de la valeur du sommet
for (int i = 7; i >= 0; i--) {
putBuffer((tree->name & (1 << i)) != 0, buffer);
}
}
}
HufTree readTree(ReadBuffer* buffer) {
HufTree tree = malloc(sizeof(*tree));
if (getBuffer(buffer) == 1) {
// Sommet avec enfants
tree->child_l = readTree(buffer);
tree->child_r = readTree(buffer);
} else {
// Feuille de l'arbre
int name = 0;
for (int i = 7; i >= 0; i--) { for (int i = 7; i >= 0; i--) {
pushToBuffer( name |= getBuffer(buffer) << i;
// Écriture du n-ième bit du caractère du fils
// dans le tampon
(vertex.name & (1 << i)) != 0,
buffer
);
} }
// Séquence de 9 bits indiquant un sommet tree->name = name;
// sans fils (100000001) tree->child_l = NULL;
pushToBuffer(1, buffer); tree->child_r = NULL;
for (int i = 0; i < 7; i++) {
pushToBuffer(0, buffer);
} }
pushToBuffer(1, buffer); return tree;
}
}
HufTree readTree(FILE* output) {
// TODO: implémenter la lecture des arbres
exit(0);
} }
void freeTree(HufTree tree) { void freeTree(HufTree tree) {
_freeTreeVertex(tree.root); if (tree->child_l != NULL && tree->child_r != NULL) {
tree.root = NULL; freeTree(tree->child_l);
freeTree(tree->child_r);
} }
void _freeTreeVertex(HufVertex* vert) { free(tree);
if (vert->child_l != NULL && vert->child_r != NULL) {
_freeTreeVertex(vert->child_l);
_freeTreeVertex(vert->child_r);
}
free(vert);
} }
char** createTreeLabels(HufTree input) { char** createTreeLabels(HufTree input) {
@ -217,7 +189,7 @@ char** createTreeLabels(HufTree input) {
labels[i] = NULL; labels[i] = NULL;
} }
_labelVertex(*input.root, labels, NULL, 0); _labelVertex(*input, labels, NULL, 0);
return labels; return labels;
} }