forked from menault/2026_TD1_DEV51_Qualite_Algo
Remplacement de la recherche dichotomique par une table de hachage
This commit is contained in:
+47
-26
@@ -26,6 +26,8 @@
|
||||
#define NB_MOTS_VOCAB 7000
|
||||
#define TAILLE_MOT 32
|
||||
#define MAX_MOTS_UNIQUES 20000
|
||||
/* Toujours moins de 50 % de cases occupées, même au maximum de mots. */
|
||||
#define TAILLE_HACHAGE (2 * MAX_MOTS_UNIQUES + 1)
|
||||
#define GRAINE 20261006UL
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -235,44 +237,54 @@ int est_mot_vide(const char *mot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Le tableau reste trié alphabétiquement pendant le comptage.
|
||||
* Renvoie l'indice du mot, ou -(position d'insertion + 1) s'il est absent. */
|
||||
int chercher_mot(Entree *table, int nb_entrees, const char *mot)
|
||||
unsigned int hacher_mot(const char *mot)
|
||||
{
|
||||
int debut = 0;
|
||||
int fin = nb_entrees - 1;
|
||||
|
||||
while (debut <= fin) {
|
||||
int milieu = debut + (fin - debut) / 2;
|
||||
int comparaison = comparer(table[milieu].mot, mot);
|
||||
if (comparaison == 0)
|
||||
return milieu;
|
||||
if (comparaison < 0)
|
||||
debut = milieu + 1;
|
||||
else
|
||||
fin = milieu - 1;
|
||||
unsigned int h = 2166136261u;
|
||||
for (int i = 0; mot[i] != '\0'; i++) {
|
||||
h ^= (unsigned char)mot[i];
|
||||
h *= 16777619u;
|
||||
}
|
||||
return -(debut + 1);
|
||||
return h;
|
||||
}
|
||||
|
||||
void compter_mot(Entree *table, int *nb_entrees, const char *mot)
|
||||
/* L'index contient indice + 1 ; zéro désigne une case libre.
|
||||
* Renvoie l'indice du mot, ou -(case libre + 1) s'il est absent. */
|
||||
int chercher_mot(const Entree *table, const int *index_mots, const char *mot)
|
||||
{
|
||||
int indice = chercher_mot(table, *nb_entrees, mot);
|
||||
int position = hacher_mot(mot) % TAILLE_HACHAGE;
|
||||
|
||||
while (index_mots[position] != 0) {
|
||||
int indice = index_mots[position] - 1;
|
||||
if (egales(table[indice].mot, mot))
|
||||
return indice;
|
||||
/* Collision : essayer la case suivante, avec retour au début. */
|
||||
position = (position + 1) % TAILLE_HACHAGE;
|
||||
}
|
||||
return -(position + 1);
|
||||
}
|
||||
|
||||
void compter_mot(Entree *table, int *nb_entrees, int *index_mots, const char *mot)
|
||||
{
|
||||
int indice = chercher_mot(table, index_mots, mot);
|
||||
if (indice >= 0) {
|
||||
table[indice].occurrences++;
|
||||
} else {
|
||||
indice = -indice - 1;
|
||||
/* Décaler uniquement lors de la première apparition d'un mot. */
|
||||
for (int i = *nb_entrees; i > indice; i--)
|
||||
table[i] = table[i - 1];
|
||||
if (*nb_entrees >= MAX_MOTS_UNIQUES) {
|
||||
fprintf(stderr, "Trop de mots distincts (maximum : %d).\n",
|
||||
MAX_MOTS_UNIQUES);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int position = -indice - 1;
|
||||
indice = *nb_entrees;
|
||||
copier(table[indice].mot, mot);
|
||||
table[indice].occurrences = 1;
|
||||
index_mots[position] = indice + 1;
|
||||
(*nb_entrees)++;
|
||||
}
|
||||
}
|
||||
|
||||
void compter_mots_ligne(Entree *table, int *nb_entrees, const char *ligne,
|
||||
long *nb_mots_total)
|
||||
void compter_mots_ligne(Entree *table, int *nb_entrees, int *index_mots,
|
||||
const char *ligne, long *nb_mots_total)
|
||||
{
|
||||
char mot[TAILLE_MOT];
|
||||
int i = 0;
|
||||
@@ -290,7 +302,7 @@ void compter_mots_ligne(Entree *table, int *nb_entrees, const char *ligne,
|
||||
if (k > 0) {
|
||||
(*nb_mots_total)++;
|
||||
if (!est_mot_vide(mot))
|
||||
compter_mot(table, nb_entrees, mot);
|
||||
compter_mot(table, nb_entrees, index_mots, mot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,11 +440,20 @@ int main(void)
|
||||
normaliser_ligne(lignes[i]);
|
||||
|
||||
Entree *table = malloc(MAX_MOTS_UNIQUES * sizeof(Entree));
|
||||
int *index_mots = calloc(TAILLE_HACHAGE, sizeof(int));
|
||||
if (table == NULL || index_mots == NULL) {
|
||||
fprintf(stderr, "Allocation du tableau de comptage impossible.\n");
|
||||
free(table);
|
||||
free(index_mots);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int nb_entrees = 0;
|
||||
long nb_mots_total = 0;
|
||||
for (int i = 0; i < nb_lignes; i++)
|
||||
compter_mots_ligne(table, &nb_entrees, lignes[i], &nb_mots_total);
|
||||
compter_mots_ligne(table, &nb_entrees, index_mots, lignes[i], &nb_mots_total);
|
||||
|
||||
/* Le tri déplace les entrées : l'index ne sert que pendant le comptage. */
|
||||
free(index_mots);
|
||||
trier_entrees(table, nb_entrees);
|
||||
|
||||
double moyenne = longueur_moyenne(table, nb_entrees);
|
||||
|
||||
Reference in New Issue
Block a user