diff --git a/analyseur.c b/analyseur.c index 1192fd0..500a1c6 100644 --- a/analyseur.c +++ b/analyseur.c @@ -14,7 +14,7 @@ * L'empreinte affichée à la fin doit rester IDENTIQUE après optimisation : * elle prouve que le résultat du programme n'a pas changé. * - * Compilation : gcc -O0 -g -pg analyseur.c -o analyseur + * Compilation : gcc -O0 -pg analyseur.c -o analyseur * Exécution : ./analyseur * Profil : gprof ./analyseur gmon.out > profil.txt */ @@ -235,23 +235,49 @@ int est_mot_vide(const char *mot) return 0; } -int chercher_mot(Entree *table, int nb_entrees, const char *mot) +/* Indices + 1 : zéro représente une case libre. Charge < 31 %. */ +#define CAPACITE_INDEX 65536 +static int index_mots[CAPACITE_INDEX]; + +unsigned long hacher_mot(const char *mot) { - for (int i = 0; i < nb_entrees; i++) { - if (egales(table[i].mot, mot)) - return i; + unsigned long h = 5381; + for (int i = 0; mot[i] != '\0'; i++) + h = h * 33 + (unsigned char)mot[i]; + return h; +} + +int chercher_mot(Entree *table, const char *mot, unsigned long *case_libre) +{ + unsigned long position = hacher_mot(mot) % CAPACITE_INDEX; + while (index_mots[position] != 0) { + int indice = index_mots[position] - 1; + if (egales(table[indice].mot, mot)) + return indice; + position = (position + 1) % CAPACITE_INDEX; } + *case_libre = position; return -1; } void compter_mot(Entree *table, int *nb_entrees, const char *mot) { - int indice = chercher_mot(table, *nb_entrees, mot); + /* Réinitialisation possible pour un nouveau comptage. */ + if (*nb_entrees == 0) + for (int i = 0; i < CAPACITE_INDEX; i++) + index_mots[i] = 0; + unsigned long position; + int indice = chercher_mot(table, mot, &position); if (indice >= 0) { table[indice].occurrences++; } else { + if (*nb_entrees == MAX_MOTS_UNIQUES) { + fputs("Trop de mots distincts\n", stderr); + exit(EXIT_FAILURE); + } copier(table[*nb_entrees].mot, mot); table[*nb_entrees].occurrences = 1; + index_mots[position] = *nb_entrees + 1; (*nb_entrees)++; } }