From 8ce897ce339116bd80e091fb03cfb91ec1eccfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre=20=E2=9C=8F?= Date: Wed, 12 Oct 2016 12:28:38 +0200 Subject: [PATCH] Implantation de l'algorithme de construction de l'arbre Ajout d'un programme principal de test --- Makefile | 8 ++--- compress | Bin 8912 -> 0 bytes include/huf.h | 23 +++++++++--- src/huf.c | 96 ++++++++++++++++++++++++++++++++++++++++++-------- src/huf.o | Bin 2136 -> 0 bytes src/main.c | 25 ++++++++++--- src/main.o | Bin 2080 -> 0 bytes 7 files changed, 126 insertions(+), 26 deletions(-) delete mode 100755 compress delete mode 100644 src/huf.o delete mode 100644 src/main.o diff --git a/Makefile b/Makefile index efd3ce3..9dd0385 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,11 @@ FLAGS=-Wall -std=c99 SRC=src PROG=compress -all: $(SRC)/main.o $(SRC)/huf.o +all: main.o huf.o $(CC) $^ $(FLAGS) -o $(PROG) -%.o: %.cpp +%.o: src/%.c $(CC) $(FLAGS) -c $^ -camille: - rm -f $(PROG) **/*.o **/*.gch +clean: + rm -f $(PROG) *.o diff --git a/compress b/compress deleted file mode 100755 index eccd93457ea79faefbb2eba632be08874530f6bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8912 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 Nhy%Ez7US0b{{v2lqmTdq diff --git a/include/huf.h b/include/huf.h index 50a1a73..0d596de 100644 --- a/include/huf.h +++ b/include/huf.h @@ -1,6 +1,12 @@ #ifndef __FREQ_H__ #define __FREQ_H__ +#include + +#define TRUE 1 +#define FALSE 0 +#define NUM_CHARS 256 + typedef struct Vertex Vertex; struct Vertex { // le double `freq` indique la fréquence d'apparition de la lettre @@ -11,18 +17,27 @@ struct Vertex { // représente (caractère ASCII 0 - 255) char value; - // pointe vers le sommet parent à celui-ci (ou bien vers NULL s'il n'a - // pas de parent affecté, comme c'est le cas pour les sommets non-traités - // et pour la racine) + // les sommets virtuels sont ceux qui ne correspondent pas à une lettre + // du corpus, mais chapeautent les autres sommets + int is_virtual; + + // pointe vers le sommet parent à celui-ci, ou NULL s'il n'a pas de parent, + // comme par exemple pour la racine et les sommets en cours de traitement Vertex* parent; }; +typedef struct Tree Tree; +struct Tree { + size_t size; + Vertex* vertices; +}; + // calcule un tableau des fréquences des caractères dans le corpus, // indexé par la valeur numérique ASCII de chaque caractère double* computeFrequencies(const char* filepath); // déduit du tableau de fréquences l'arbre de Huffman, représenté // par une liste de sommets chaînés -Vertex* buildTree(double* frequencies); +Tree buildTree(double* frequencies); #endif diff --git a/src/huf.c b/src/huf.c index 635508d..4296dff 100644 --- a/src/huf.c +++ b/src/huf.c @@ -1,13 +1,14 @@ #include "../include/huf.h" +#include #include #include double* computeFrequencies(const char* filepath) { - double* frequencies = (double*) malloc(256 * sizeof(double)); + double* frequencies = (double*) malloc(NUM_CHARS * sizeof(double)); int totalChars = 0; // initialisation du tableau à 0 - for (int i = 0; i < 256; i++) { + for (size_t i = 0; i < NUM_CHARS; i++) { frequencies[i] = 0; } @@ -21,30 +22,97 @@ double* computeFrequencies(const char* filepath) { } // conversion des effectifs en fréquences - for (int i = 0; i < 256; i++) { + for (size_t i = 0; i < NUM_CHARS; i++) { frequencies[i] /= totalChars; } return frequencies; } -Vertex* buildTree(double* frequencies) { - int vertexCount = 0; +Tree buildTree(double* frequencies) { + // comptage du nombre de caractères différents dans le fichier, + // il s'agit du nombre initial de sommets dans l'arbre binaire + size_t vertex_count = 0; - // on compte le nombre de sommets à allouer - // (uniquement les caractères qui apparaissent au moins une fois) - for (int i = 0; i < 256; i++) { + for (size_t i = 0; i < NUM_CHARS; i++) { if (frequencies[i] > 0) { - vertexCount++; + vertex_count++; } } - // on alloue la place pour 2n + 1 sommets (nombre total - // de sommets dans l'arbre binaire) - Vertex* tree = (Vertex*) malloc((2 * vertexCount - 1) * sizeof(Vertex)); + // allocation d'un tableau de 2n + 1 sommets, le nombre total de + // sommets dans l'arbre binaire final + size_t tree_size = 2 * vertex_count - 1; + Vertex* vertices = (Vertex*) malloc(tree_size * sizeof(Vertex)); - // (à faire: algo pour remplir l'arbre) - // (trier le tableau des fréquences ?) + // remplissage initial du tableau avec un sommet pour chaque lettre + size_t next_available = 0; + + for (size_t i = 0; i < NUM_CHARS; i++) { + if (frequencies[i] > 0) { + vertices[next_available].frequency = frequencies[i]; + vertices[next_available].value = (char) i; + vertices[next_available].is_virtual = FALSE; + vertices[next_available].parent = NULL; + next_available++; + } + } + + // remplissage du tableau avec les sommets virtuels + while (next_available < tree_size) { + // détermination des deux sommets de fréquence les plus faibles + // parmi tous les sommets n'ayant pas de parent + size_t i = 0, min_vert, min_vert_sec; + int is_init = FALSE, is_init_sec = FALSE; + double min_freq; + + for (; i < next_available; i++) { + if (vertices[i].parent == NULL) { + if (!is_init) { + // initialisation du premier sommet sans parent + min_vert = i; + min_freq = vertices[i].frequency; + is_init = TRUE; + } else if (!is_init_sec) { + // initialisation du second sommet sans parent, + // en s'assurant qu'ils sont dans le bon ordre + if (vertices[i].frequency < min_freq) { + size_t swap = min_vert; + min_vert = i; + min_vert_sec = swap; + min_freq = vertices[i].frequency; + } else { + min_vert_sec = i; + } + + is_init_sec = TRUE; + } else if (vertices[i].frequency < min_freq) { + // déplacement de l'ancien minimum en second minimum + // et remplacement par le nouveau minimum + min_vert_sec = min_vert; + min_vert = i; + } + } + } + + // création d'un sommet parent à ces deux sommets. Ce sommet est + // créé à la prochaine position disponible dans le tableau + vertices[next_available].frequency = + vertices[min_vert].frequency + vertices[min_vert_sec].frequency; + vertices[next_available].is_virtual = TRUE; + vertices[next_available].parent = NULL; + + // assignation du nouveau parent et des enfants + vertices[min_vert].parent = &vertices[next_available]; + vertices[min_vert_sec].parent = &vertices[next_available]; + + next_available++; + } + + Tree tree = { + .size = tree_size, + .vertices = vertices + }; return tree; } diff --git a/src/huf.o b/src/huf.o deleted file mode 100644 index 0f781c43117d76329c66bf6e5484ec2abab1b8a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2136 zcmb_c&rcIU6n;xleh6+c9EfSxHxRBI=Lzvf2h|mRA<%@`vb}|Eg!%?y617Kmp+{F&*`6!Dta=-9 z*tM0_@eN07UqOijokzc7dkb@WhpDw3E0StqB+H6bm1KiO-T168w|ucPXMUMD5}^idb*auJ;`#D{XJ`M)Oi-#6qR@?W9gcCMhj7z1V2t8}(B zG_K%-IEOe5vL<>UH&1()>V{iSdg>LV*uHDF7hslV;jc@Q`&c8XdiY6)t};)}mk8j& zzgp%&rCR0z>G4Vg4>U--qos%5aSijp$tsi-&Pa9Iy+Q0O4sR73;QTT8#bfYZ#7ST1 z+Px*+$y7u$z=%g@QkFTAFrTK(m@#E0AsU*VjvEk(&zLcYJT@%@!l|k0iF*mtBrV74 zaB9Z!>(H@rjuR$#>k-F^e+q}-FG)D@Md#m0c#FhO(nX`W^ZIPm!O15qz!!wk5a$Oi z`8;Zc!Z=$AXPy+RggG73EOXWZZ6aiaKno|6pe5qY23r+1W9W;;EmIr46YNb|A>#=W zD9oIE7)gYp*rESpK9r#&yI)KIF|tM84`=6a#hT_$9MsbQ4%tfl>925*?u4Yoi|yd} z1&+JFlnqy2PM2P=gY@7;n*SQ#hq07OzEj-77SHegHbnizA)|jrMD^1~vRxiOC}FhZ z@SpjXgvr!acR}1K;sy6Uk9X6(91!1&;JfP|Lr1OqTi_pxI2YX?#fo@we{G1ldyf#j o\n"); - printf("Paramètre fichier manquant.\n"); + fprintf(stderr, "Usage : compress \n"); + fprintf(stderr, "Paramètre fichier manquant.\n"); return 1; } double* frequencies = computeFrequencies(argv[1]); double sum = 0; + printf("--- 1 : CALCUL DES FRÉQUENCES ---\n\n"); + for (int i = 0; i < 256; i++) { if (frequencies[i] != 0) { sum += frequencies[i]; - printf("%c (%d) : %f\n", i, i, frequencies[i]); + printf("%1c (%3d) : %4f\n", i, i, frequencies[i]); } } - printf("Total : %f\n", sum); + printf("Total : %f\n\n", sum); + printf("--- 2 : CONSTRUCTION DE L'ARBRE ---\n\n"); + + Tree tree = buildTree(frequencies); + printf("Arbre à %zu sommets\n\n", tree.size); + + for (int i = 0; i < tree.size; i++) { + Vertex* vertex = &tree.vertices[i]; + + printf( + "[%p] Sommet %c (%4f, %s) : parent %p\n", + (void*) vertex, vertex->value, vertex->frequency, + vertex->is_virtual ? "est virtuel" : "non virtuel", + (void*) vertex->parent + ); + } return 0; } diff --git a/src/main.o b/src/main.o deleted file mode 100644 index 42f25880a0b3558a037c4638fadceccfa1221ac3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2080 zcmbtU&r1|h9RJR)rES`-Ar&Ywmkos+c10JHkWCq#Lq**<5mWb>k7KlJbt9;kWwRB~1TdUYx<;Cp~yZoLAJM=lymMQA)5Bz9V zbxSL+G-*}PD(enStEdOL=+Bk?Xsf!nuGYwPcL_gLwWht%mfAiLf{q88w6!0N0g^X! zQDt=@A~bgYBrfvD_V%L_t4{PFmR4=5W@@xj8QVa*x>5P)RPGe*R9IGP((}by9m|Nm z%GK+2EM^bOcIiIyGF7{|ma+6lhCCo=ONCj}uq^p{E}xyw8|EO~)=j;z_LiB3%rUv3 z7w2rf$P|cY<<9t27kb8X5x7%g`V7}$ba;3`?#xWuMP|!=O0SaWPT7u?e40!tiC(3r z%f;oML^72~C9Y8|0B!CB(!w}M^D(Ktxv}Xrwxk1b8YCUmq8sO8FG9mDr^6Q|q&Rrc zho}wki_YVigadC7Kp1~P62?eD5{6SjFh*%S0S~S>45yFriFw{rr?Yp&T5!aUv56au z$4|hapy!K9)|p_|W){#bu$eJp8gsT$%;pUXX3cz&<(zC6c+LpU-d(qIJcKi?{l=?D zB6D2u1&`_>@$-jV*ul@DF5-OVxQNrw?Qb4_vxnbEjYkpu5!ZxPj#FMQU*_wC(>N5x zdQxEeBq$a$-FaGQrZJ-{%$R4OOzBJqWzw=hF-xw2=U6a`xK=DNLm9o5>9&}jeT)Qh zGo~Np@M#%`dHz$8(Vw>Fzd>olNW{HyEte~FnyD{zyVE$l@{&J=PaLG4P#$rEFLC?| z$Newo9zSnRJDmLRRa~K%|LUJaUyAux@6Z&NUpP#Ux{1Y6c`{5OT{y!$%0EGYm